溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

jd-gui 反編譯出現(xiàn)access$分析和函數(shù)說明什么

發(fā)布時(shí)間:2021-10-14 09:59:34 來源:億速云 閱讀:783 作者:柒染 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)jd-gui 反編譯出現(xiàn)access$分析和函數(shù)說明什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

1)static Type access$iii(Outer); 是JAVA編譯器自動(dòng)生成的十分重要的方法(該方法的個(gè)數(shù)由你的內(nèi)部類要訪問的外部類的變量個(gè)數(shù)相關(guān)),目的是:用于內(nèi)部類訪問外部類的數(shù)據(jù)成員時(shí)使用.

2)因此:JAVA編譯器在生成內(nèi)部類的訪問外部類的數(shù)據(jù)成員時(shí),會(huì)自動(dòng)生成代碼來調(diào)用這個(gè)方法.
以你的代碼為例:內(nèi)部類Inner中的方法
public int getDate() { 
return xx; 

生成的代碼如下:(經(jīng)javap 處理后)
Java code

?

1 2 3 4 5 6 7 8 9 10 11 12public int getDate();  LineNumberTable:   line 120       Code:   Stack=1, Locals=1, Args_size=1   0:   aload_0   1:   getfield        #1//Field this$0:LOuter;   4:   invokestatic    #3//Method Outer.access$000:(LOuter;)I   7:   ireturn


看代碼第4行:通過Outer.access$000(Outer o)來獲取外部類對象o中的private型的數(shù)據(jù)成員(請注意:這可是從另外一個(gè)類中訪問其它類的private型數(shù)據(jù)成員--不是通過反射技術(shù))

3)進(jìn)一步:
若外部類定義了兩個(gè)private 數(shù)據(jù)成員如下:
private int xx=12;
private float yy=12.4f;
這兩個(gè)數(shù)據(jù)成員在內(nèi)部類中都要訪問,則編譯器會(huì)自動(dòng)生成兩個(gè)access方法:
static int access$000(Outer);  用于內(nèi)部類訪問private int xx;
static float access$100(Outer);  用于內(nèi)部類訪問private float yy;

4)這種內(nèi)部類訪問外部類中private數(shù)據(jù)成員的技術(shù)(不是通過反射!) 給安全留下了可能的小隱患(因?yàn)橛行﹑rivate數(shù)據(jù)成員是不提供外界訪問它的所謂的getter()的).為此,編譯器對自己自動(dòng)生成的這些access$000()方法,在編譯時(shí)進(jìn)行檢查,是不允許程序員直接來調(diào)用的.

但是:我們可以利用JAVA編譯器對類的編譯特性來繞過這個(gè)檢查:目的是,達(dá)到在自己的其它類中直接來調(diào)用這些access$000()方法.
這樣,我們可采用這個(gè)技術(shù)(即:在自己的類中--注意不是內(nèi)部類,而是外部類中直接來調(diào)用這個(gè)access$000(Outer);)來訪問其它類的private的數(shù)據(jù)成員了.

具體技術(shù)演示如下:
第一步:定義如下的類:
class Outer { 
private final int xx = 123;  
//由于是final,故不再自動(dòng)生成access$000(Outer);

public Inner getInner() { 
return new Inner(); 

public class Inner { 
public int getDate() { 
return xx; 

} //class Inner

 static int access$000(Outer)//這個(gè)是自已定義的!
 {
  return  1;
 } 


第二步:定義你的其它類,來直接調(diào)用這個(gè)access$000()方法
public class Test1
{
 public static void main(String[] args)
 {

  System.out.println(Outer.access$000(new Outer()));  //這個(gè)調(diào)用是沒有問題的,因?yàn)槭亲约憾x的!
 }

}

將上述兩個(gè)JAVA文件編譯成class,成其是第二步的 Test1.class

第三步:這是變戲法的一步:
將第一步的類Outer改為如下:
class Outer { 
private  int xx = 123;  
//由于不是final,故自動(dòng)生成access$000(Outer);

public Inner getInner() { 
return new Inner(); 

public class Inner { 
public int getDate() { 
return xx; 

} //class Inner
/*將這個(gè)第一步中自己定義的access$000去掉,因?yàn)榫幾g器會(huì)自動(dòng)生成它!
 static int access$000(Outer {
  return  1;
 } */

重新編譯第三步中的這個(gè)類,而第二步中的類Test.class不動(dòng)它. 此時(shí),我們達(dá)到了這樣一個(gè)目的:在類Test1中調(diào)用了Outer類中編譯器自動(dòng)生成的這個(gè)access$000(...)了.

----上篇借鑒別人的--

使用jd-gui反編譯后去掉注釋 /\*
*\d* *\*/

此處略作修改:\/\* *\d* *\*\/

去掉最后一行自動(dòng)生成的注釋 /\* Location:[\S\s]+?(?=\*/)\*/$

.access$ 反編譯偶內(nèi)部類調(diào)用外部類成員問題
很簡單的一個(gè)測試類源碼: 
public class testOuter {
private int a;
private int b;

private void fun() {
a += 1;
}

class testInner {
int x = 0;
testInner() {
b = 1;
a = 0;
fun();
}
}
編譯生成的Class文件:
class testOuter$testInner {
int x = 0;
testOuter$testInner(testOuter paramtestOuter) {
testOuter.access$002(paramtestOuter, 1);
testOuter.access$102(paramtestOuter, 0);
testOuter.access$200(paramtestOuter);
}
}
可以看出,為了使內(nèi)部類訪問外部類的私有成員,編譯器生成了形似 “外部類.access$XYZ”的函數(shù)。XYZ為數(shù)字。X是按照私有成員在內(nèi)部類出現(xiàn)的順序遞增的。8是 service , YZ為02的話,標(biāo)明是基本變量成員;YZ為00的話標(biāo)明是對象成員或者函數(shù),YZ為08的話標(biāo)明是對象成員或者函數(shù)。

這些參數(shù)可以得出一張表對應(yīng)表,等待整理 

.....sionManager.access$102(..nManager.this, null);

關(guān)于jd-gui 反編譯出現(xiàn)access$分析和函數(shù)說明什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI