⑴ java 如何反編譯得到源文件的private類
下個反編譯工具,如JD-GUI。可以將.class文件轉為java文件
⑵ 反編譯java核心類 能不能反編譯java核心類,比如java.lang.String,再編寫自己的代碼放到裡面去
我估計你是想重編譯String.class文件並覆蓋吧,這個目前行不通,據說像HotSpot這種商業JVM內部都存有一張關於核心類庫的裝載信息表專供根載入器使用,這個表內容是以通過硬寫在JVM底層C\C++程序中的方式存在的,在裝載核心類庫的.Jar文件時不僅要比對其中.class文件的有效性,還要比較.Jar文件的SHA1哈希值與裝載信息表中的記錄是否一致!(或許哈希弱無碰撞演算法出現時會有希望,呵呵)同時JVM會運行各種安全沙箱機制(比如裝載約束、訪問許可權等等)來保護運行環境的安全性,所以除非重編譯JVM否則目前沒有什麼好方法。
⑶ 有沒有比較完美的JAVA反編譯方法
1、Java反編譯插件 —— Jadclipse JadClipse是Jad的Eclipse插件,是一款非常實用而且方便地Java反編譯插件,我們只需將下載的插件包復制到eclipse的plugins目錄下,然後修改window -> Preferences -> Java -> JadClipse
⑷ 什麼是Java代碼的編譯與反編譯
java代碼的編譯,就是你寫完代碼,java編譯器把它編譯成java虛擬機認識的代碼,然後再由虛擬機執行它。反編譯就是反過來,當然這不是java虛擬機乾的事兒,是你找反編譯工具乾的事兒,把編譯過的代碼反編譯成人看得懂的源代碼。
⑸ 怎麼將java類反編譯成class文件
工具:
dj
java
discompiler
方法
1.
打開dj_java_discompiler,選擇file--open,打開class文件
2.
從下圖就可以看到已經反編譯了
3.
下圖為java源文件,可以對比沒有任何問題
⑹ 如何將java中的.class文件反編譯
安裝Java jdk後
看安裝目錄里有沒有jad.exe,沒有要下載,一般都有的
配置Java環境變數
開始-運行-cmd-回車-進入命令行窗口:
cd+空格+class文件所在路徑:
按下面的命令進行反編譯:
例如:[2] jad -sjava example.class 回車
在目錄里可以看到example.java源文件
[1] 反編譯一個class文件:jad example.class,會生成example.jad,用文本編輯器打開就是java源代碼
[2] 指定生成源代碼的後綴名:jad -sjava example.class,生成example.java
[3] 改變生成的源代碼的名稱,可以先使用-p將反編譯後的源代碼輸出到控制台窗口,然後使用重定向,輸出到文件:jad -p example.class > myexample.java
[4] 把源代碼文件輸出到指定的目錄:jad -dnewdir -sjava example.class,在newdir目錄下生成example.java
[5] 把packages目錄下的class文件全部反編譯:jad -sjava packages/*.class
[6] 把packages目錄以及子目錄下的文件全部反編譯:jad -sjava packages/**/*.class,不過你仍然會發現所有的源代碼文件被放到了同一個文件中,沒有按照class文件的包路徑建立起路徑
[7] 把packages目錄以及子目錄下的文件全部反編譯並建立和java包一致的文件夾路徑,可以使用-r命令:jad -r -sjava packages/**/*.class
[8] 當重復使用命令反編譯時,Jad會提示「whether you want to overwrite it or not」,使用-o可以強制覆蓋舊文件
[9] 還有其他的參數可以設置生成的源代碼的格式,可以輸入jad命令查看幫助,這里有個人做了簡單的翻譯:jad命令總結
[10] 當然,你會發現有些源文件頭部有些注釋信息,不用找了,jad沒有參數可以去掉它,用別的辦法吧。
⑺ java類反編譯
額..那源代碼改一下.然後編譯覆蓋不就得了.還反編譯.然後再編譯...唉.坐等高人...
⑻ Java代理的作用和實現
JDK 動態代理
動態代理的核心其實就是代理對象的生成,即 Proxy.newProxyInstance(classLoader, proxyInterface, handler)。
讓我們進入newProxyInstance方法觀摩下,核心代碼其實就三行。
這個方法需要三個參數:
ClassLoader,用於載入代理類的 Loader 類,通常這個 Loader 和被代理的類是同一個 Loader 類。
Interfaces,是要被代理的那些那些介面。
InvocationHandler,就是用於執行除了被代理介面中方法之外的用戶自定義的操作,也是用戶需要代理的最終目的。用戶調用目標方法都被代理到 InvocationHandler 類中定義的唯一方法 invoke 中。
- //獲取代理類 Class cl = getProxyClass(loader, interfaces);
- //獲取帶有InvocationHandler參數的構造方法 Constructor cons = cl.getConstructor(constructorParams);
- //把handler傳入構造方法生成實例 return (Object) cons.newInstance(new Object[] { h });
一個典型的動態代理創建對象過程可分為以下四個步驟:
1、通過實現InvocationHandler介面創建調用處理器
- IvocationHandler handler = new InvocationHandlerImpl(...);
2、通過為Proxy類指定ClassLoader對象和一組interface創建動態代理類
- Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通過反射機制獲取動態代理類的構造函數,其參數類型是調用處理器介面類型
- Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通過構造函數創建代理類實例,此時需將調用處理器對象作為參數被傳入
- Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
為了簡化對象創建過程,Proxy類中的newProxyInstance方法封裝了2~4,只需兩步即可完成代理對象的創建。
- Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
- new Class[]{Subject.class}, new InvocationHandlerImpl (real));
生成的proxySubject繼承Proxy類實現Subject介面。實現的Subject的方法實際是調用處理器的invoke方法,而invoke方法利用反射調用的是被代理對象的方法(Object result=method.invoke(proxied,args));
重點Proxy.newProxyInstance,源碼分析,會在其他文檔中單獨總結記錄。類Proxy的getProxyClass方法調用ProxyGenerator的 generateProxyClass方法產生ProxySubject.class的二進制數據。
創建代理對象時序圖

獲取代理類
getProxyClass(loader, interfaces)方法用於獲取代理類,它主要做了三件事情:
在當前類載入器的緩存里搜索是否有代理類,沒有則生成代理類並緩存在本地JVM里。
- // 緩存的key使用介面名稱生成的List Object key = Arrays.asList(interfaceNames);
- synchronized (cache) {
- do {
- Object value = cache.get(key);
- // 緩存里保存了代理類的引用 if (value instanceof Reference) {
- proxyClass = (Class) ((Reference) value).get();
- }
- if (proxyClass != null) {
- // 代理類已經存在則返回
- return proxyClass;
- } else if (value == pendingGenerationMarker) {
- // 如果代理類正在產生,則等待
- try {
- cache.wait();
- } catch (InterruptedException e) {
- }
- continue;
- } else {
- //沒有代理類,則標記代理准備生成
- cache.put(key, pendingGenerationMarker);
- break;
- }
- } while (true);
- }
生成並載入代理類
代理類的生成主要是以下這兩行代碼:
- //生成代理類的位元組碼文件並保存到硬碟中(默認不保存到硬碟) proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
- //使用類載入器將位元組碼載入到內存中 proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
代理類的生成過程
ProxyGenerator.generateProxyClass()方法屬於sun.misc包下,Oracle並沒有提供源代碼,但是我們可以使用
JD-GUI這樣的反編譯軟體打開jrelib
t.jar來一探究竟,以下是其核心代碼的分析。
- //添加介面中定義的方法,此時方法體為空 for (int i = 0; i < this.interfaces.length; i++) {
- localObject1 = this.interfaces[i].getMethods();
- for (int k = 0; k < localObject1.length; k++) {
- addProxyMethod(localObject1[k], this.interfaces[i]);
- }
- }
- //添加一個帶有InvocationHandler的構造方法 MethodInfo localMethodInfo = new MethodInfo("<init>", "(Ljava/lang/reflect/InvocationHandler;)V", 1);
- //循環生成方法體代碼(省略) //方法體里生成調用InvocationHandler的invoke方法代碼。(此處有所省略) this.cp.getInterfaceMethodRef("InvocationHandler", "invoke", "Object; Method; Object;")
- //將生成的位元組碼,寫入硬碟,前面有個if判斷,默認情況下不保存到硬碟。 localFileOutputStream = new FileOutputStream(ProxyGenerator.access$000(this.val$name) + ".class");
- localFileOutputStream.write(this.val$classFile);
生成的代理類源碼
那麼通過以上分析,我們可以推出動態代理為我們生成了一個這樣的代理類。把方法doSomeThing的方法體修改為調用LogInvocationHandler的invoke方法。
- public class ProxyBusiness extends Proxy implements IBusiness, IBusiness2 {
- private LogInvocationHandler h;
- @Override public void doSomeThing2() {
- try {
- Method m = (h.target).getClass().getMethod("doSomeThing2",null);
- h.invoke(this, m, null);
- } catch (Throwable e) {
- // 異常處理(略)
- }
- }
- @Override public boolean doSomeThing() {
- try {
- Method m = (h.target).getClass().getMethod("doSomeThing", null);
- return (Boolean) h.invoke(this, m, null);
- } catch (Throwable e) {
- // 異常處理(略)
- }
- return false;
- }
- public ProxyBusiness(LogInvocationHandler h) {
- this.h = h;
- }
測試代理的代碼如下:
- //測試public static void main(String[] args) {
- //構建AOP的Advice
- LogInvocationHandler handler = new LogInvocationHandler(new Business());
- new ProxyBusiness(handler).doSomeThing();
- new ProxyBusiness(handler).doSomeThing2();
- }
下面看一個自定義代理的實現。
被代理類介面
- public interface Subject {
- public void doSomething();
- }
被代理類
- //目標對象public class RealSubject implements Subject{ public void doSomething() {
- System.out.println( "call doSomething()" );
- }
- }
調用處理器(切面)
- public class ProxyHandler implements InvocationHandler {
- private Object proxied;
- public ProxyHandler( Object proxied ) {
- this.proxied = proxied;
- }
- public Object invoke( Object proxy, Method method, Object[] args ) throws Throwable {
- //在轉調具體目標對象之前,可以執行一些功能處理System.out.println( "doSomething before" ); //轉調具體目標對象的方法
- return method.invoke( proxied, args);
- //在轉調具體目標對象之後,可以執行一些功能處理System.out.println( "doSomething after" );
- }
- }
測試我們的代理實現
- public class DynamicProxy {
- public static void main( String args[] ) {
- RealSubject real = new RealSubject();
- Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
- new Class[]{Subject.class}, new ProxyHandler(real));
- proxySubject.doSomething(); //write proxySubject class binary data to file
- createProxyClassFile();
- }
- public static void createProxyClassFile() {
- String name = "ProxySubject";
- byte[] data = ProxyGenerator.generateProxyClass( name, new Class[] { Subject.class } );
- try{
- FileOutputStream out = new FileOutputStream( name + ".class" );
- out.write( data );
- out.close();
- }catch( Exception e ) {
- e.printStackTrace();
- }
- }
- }
運行結果:
- doSomething beforecall doSomething()doSomething after
Proxy 介面
Proxy 的主要靜態變數
- // 映射表:用於維護類裝載器對象到其對應的代理類緩存private static Map loaderToCache = new WeakHashMap();// 標記:用於標記一個動態代理類正在被創建中private static Object pendingGenerationMarker = new Object();// 同步表:記錄已經被創建的動態代理類類型,主要被方法 isProxyClass 進行相關的判斷private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap());// 關聯的調用處理器引用protected InvocationHandler h;
- Proxy的構造方法// 由於 Proxy 內部從不直接調用構造函數,所以 private 類型意味著禁止任何調用private Proxy() {}// 由於 Proxy 內部從不直接調用構造函數,所以 protected 意味著只有子類可以調用protected Proxy(InvocationHandler h) {this.h = h;}
ProxySubject 源碼
創建的代理類 ProxySubject.class
- import java.lang.reflect.*;
- public final class ProxySubject extends Proxy implements Subject{
- private static Method m1;
- private static Method m0;
- private static Method m3;
- private static Method m2;
- public ProxySubject(InvocationHandler invocationhandler){
- super(invocationhandler);
- }
- public final boolean equals(Object obj){
- try {
- return ((Boolean)super.h.invoke(this, m1, new Object[] {
- obj
- })).booleanValue();
- }catch(Error _ex) {
- }catch(Throwable throwable){
- throw new UndeclaredThrowableException(throwable);
- }
- }
- public final int hashCode() {
- try {
- return ((Integer)super.h.invoke(this, m0, null)).intValue();
- }catch(Error _ex) {
- }catch(Throwable throwable){
- throw new UndeclaredThrowableException(throwable);
- }
- }
- /*關鍵部分*/
- public final void doSomething() {
- try {
- // Proxy類中protected InvocationHandler h;關聯的調用處理器引用
- super.h.invoke(this, m3, null);
- return;
- }catch(Error _ex) {
- }catch(Throwable throwable) {
- throw new UndeclaredThrowableException(throwable);
- }
- }
- public final String toString() {
- try {
- return (String)super.h.invoke(this, m2, null);
- } catch(Error _ex) {
- } catch(Throwable throwable){
- throw new UndeclaredThrowableException(throwable);
- }
- }
- static{
- try {
- m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
- Class.forName("java.lang.Object")
- });
- m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
- m3 = Class.forName("Subject").getMethod("doSomething", new Class[0]);
- m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
- }catch(NoSuchMethodException nosuchmethodexception) {
- throw new NoSuchMethodError(nosuchmethodexception.getMessage());
- }catch(ClassNotFoundException classnotfoundexception){
- throw new NoClassDefFoundError(classnotfoundexception.getMessage());
- }
- }
- }
CGLib 動態代理
動態位元組碼生成。使用動態位元組碼生成技術實現AOP原理是在運行期間目標位元組碼載入後,生成目標類的子類,將切面邏輯加入到子類中,所以使用Cglib實現AOP不需要基於介面。
- public static void main(String[] args) {
- byteCodeGe();
- }
- public static void byteCodeGe() {
- //創建一個織入器
- Enhancer enhancer = new Enhancer();
- //設置父類
- enhancer.setSuperclass(Business.class);
- //設置需要織入的邏輯
- enhancer.setCallback(new LogIntercept());
- //使用織入器創建子類
- IBusiness2 newBusiness = (IBusiness2) enhancer.create();
- newBusiness.doSomeThing2();
- }
- /**
- * 記錄日誌
- */ public static class LogIntercept implements MethodInterceptor {
- @Override
- public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {
- //執行原有邏輯,注意這里是invokeSuper
- Object rev = proxy.invokeSuper(target, args);
- //執行織入的日誌
- if (method.getName().equals("doSomeThing2")) {
- System.out.println("記錄日誌");
- }
- return rev;
- }
- }
⑼ Java的動態代理(Proxy.newInstance)是根據傳遞的參數拼接一個實現了所傳遞的介面
對,但是我們的直覺不太一樣。Proxy。newInstance方法是使用ProxyGenerator來動態生成位元組碼的,生成的是位元組碼所以沒有編譯過程。
通過ProxyGenerator生成的位元組碼代表的類繼承了Proxy類,實現了newInstance參數傳遞進來的介面,只不過是代理所以在生成的類中都是通過newInstance方法的InvocationHandler的invoke方法代理的。
可以看一下http://my.oschina.net/u/2474629/blog/703611這一篇文章,看一下ProxyGenerator生成的位元組碼反編譯之後的類的樣子,更加有助於理解Proxy方式的動態代理。
⑽ JAVA 如何反編譯的自己的程序(RCP程序)
反編譯的工具有好多, 在眾多的JAVA反編譯工具中,有幾種非常著名的工具使用了相同的核心引擎——JAD,其中主要包括:Front End Plus、mDeJava、Decafe Pro、Cavaj Java Decompiler、DJ Java Decompiler、NMI』s Java Class Viewer和國產的JAVA源代碼反編譯專家。
jad是java的反編譯工具,是命令行執行,反編譯出來的源文件可讀性較高。可惜用起來不太方便。還好
找到eclipse下的插件,叫jadclipse,安裝好之後,只要雙擊.class文件,就能直接看源文件,包括jar
包中的class文件,也可以直接反編譯。
1.下載jad1.5.8e
下載後解壓。解壓縮後將jad.exe拷貝到JRE的bin目錄下,如d:\Java\jre1.5\bin
2.下載net.sf.jadclipse_3.2.4.jar
3.安裝插件,有如下兩種方法
A.將net.sf.jadclipse_3.2.4.jar復制到D:\leaf\eclipse\plugins目錄下。
B.在d:\leaf下建立ecliplsePlungin\jadclipse\eclipse\plugins目錄,將net.sf.jadclipse_3.2.4.jar放到該目錄。在d:\leaf\eclipse\links下建jadclipse.link,內容為path=d\:\\leaf\\ecliplsePlungin\\jadclipse
3.啟動Eclipse後,在Windows(窗口)-->Perference(首選項)-->Java下面應該會多出一個JadClipse目錄,相關的設置可以在此修改配置jadclipse:設置path to decompiler為jad.exe的全路徑,如:d:\Java\jre1.5\bin\jad.exe,在Directory for temporary files中指定臨時文件的路徑,如:C:\Java\temp
4、在Eclipse的Windows-->Perference-->General->Editors->File Associations中修改「*.class」默認關聯的編輯器為「JadClipse Class File Viewer」
5、安裝完成,雙擊class文件,Eclipse將自動反編譯了。
6、把*.java 和*.class文件放在同一文件夾下,在反編譯時它回自動去尋找*.java的文件。
反編譯工具jad簡單用法
以下假設jad.exe在c:\java目錄下
一、基本用法
Usage: jad [option(s)]
直接輸入類文件名,且支持通配符,如下所示。
c:\java\>jad example1.class
c:\java\>jad *.class
結果是將example1.class反編譯為example1.jad。將example1.jad改為example1.java即得源
文件。
二、Option -o
不提示,覆蓋源文件
三、Option -s
c:\java\>jad -sjava example1.class
反編譯結果以.java為擴展名。
四、Option -p
將反編譯結果輸出到屏幕
c:\java\>jad -p example1.class
將反編譯結果重定向到文件
c:\java\>jad -p example1.class>example1.java
五、Option -d
指定反編譯的輸出文件目錄
c:\java\>jad -o -dtest -sjava *.class