jd-gui 反编译出现access$分析和函数说明
2014-09-28 17:23
246 查看
1)static Type access$iii(Outer); 是JAVA编译器自动生成的十分重要的方法(该方法的个数由你的内部类要访问的外部类的变量个数相关),目的是:用于内部类访问外部类的数据成员时使用.
2)因此:JAVA编译器在生成内部类的访问外部类的数据成员时,会自动生成代码来调用这个方法.
以你的代码为例:内部类Inner中的方法
public int getDate() {
return xx;
}
生成的代码如下:(经javap 处理后)
Java code
?
看代码第4行:通过Outer.access$000(Outer o)来获取外部类对象o中的private型的数据成员(请注意:这可是从另外一个类中访问其它类的private型数据成员--不是通过反射技术)
3)进一步:
若外部类定义了两个private 数据成员如下:
private int xx=12;
private float yy=12.4f;
这两个数据成员在内部类中都要访问,则编译器会自动生成两个access方法:
static int access$000(Outer); 用于内部类访问private int xx;
static float access$100(Outer); 用于内部类访问private float yy;
4)这种内部类访问外部类中private数据成员的技术(不是通过反射!) 给安全留下了可能的小隐患(因为有些private数据成员是不提供外界访问它的所谓的getter()的).为此,编译器对自己自动生成的这些access$000()方法,在编译时进行检查,是不允许程序员直接来调用的.
但是:我们可以利用JAVA编译器对类的编译特性来绕过这个检查:目的是,达到在自己的其它类中直接来调用这些access$000()方法.
这样,我们可采用这个技术(即:在自己的类中--注意不是内部类,而是外部类中直接来调用这个access$000(Outer);)来访问其它类的private的数据成员了.
具体技术演示如下:
第一步:定义如下的类:
class Outer {
private final int xx = 123;
//由于是final,故不再自动生成access$000(Outer);
public Inner getInner() {
return new Inner();
}
public class Inner {
public int getDate() {
return xx;
}
} //class Inner
static int access$000(Outer)//这个是自已定义的!
{
return 1;
}
第二步:定义你的其它类,来直接调用这个access$000()方法
public class Test1
{
public static void main(String[] args)
{
System.out.println(Outer.access$000(new Outer())); //这个调用是没有问题的,因为是自己定义的!
}
}
将上述两个JAVA文件编译成class,成其是第二步的 Test1.class
第三步:这是变戏法的一步:
将第一步的类Outer改为如下:
class Outer {
private int xx = 123;
//由于不是final,故自动生成access$000(Outer);
public Inner getInner() {
return new Inner();
}
public class Inner {
public int getDate() {
return xx;
}
} //class Inner
/*将这个第一步中自己定义的access$000去掉,因为编译器会自动生成它!
static int access$000(Outer {
return 1;
} */
重新编译第三步中的这个类,而第二步中的类Test.class不动它. 此时,我们达到了这样一个目的:在类Test1中调用了Outer类中编译器自动生成的这个access$000(...)了.
----上篇借鉴别人的--
使用jd-gui反编译后去掉注释 /\*
*\d* *\*/
此处略作修改:\/\* *\d* *\*\/
去掉最后一行自动生成的注释 /\* Location:[\S\s]+?(?=\*/)\*/$
.access$ 反编译偶内部类调用外部类成员问题
很简单的一个测试类源码:
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);
}
}
可以看出,为了使内部类访问外部类的私有成员,编译器生成了形似 “外部类.access$XYZ”的函数。XYZ为数字。X是按照私有成员在内部类出现的顺序递增的。8是 service , YZ为02的话,标明是基本变量成员;YZ为00的话标明是对象成员或者函数,YZ为08的话标明是对象成员或者函数。
这些参数可以得出一张表对应表,等待整理
.....sionManager.access$102(..nManager.this, null);
2)因此:JAVA编译器在生成内部类的访问外部类的数据成员时,会自动生成代码来调用这个方法.
以你的代码为例:内部类Inner中的方法
public int getDate() {
return xx;
}
生成的代码如下:(经javap 处理后)
Java code
?
3)进一步:
若外部类定义了两个private 数据成员如下:
private int xx=12;
private float yy=12.4f;
这两个数据成员在内部类中都要访问,则编译器会自动生成两个access方法:
static int access$000(Outer); 用于内部类访问private int xx;
static float access$100(Outer); 用于内部类访问private float yy;
4)这种内部类访问外部类中private数据成员的技术(不是通过反射!) 给安全留下了可能的小隐患(因为有些private数据成员是不提供外界访问它的所谓的getter()的).为此,编译器对自己自动生成的这些access$000()方法,在编译时进行检查,是不允许程序员直接来调用的.
但是:我们可以利用JAVA编译器对类的编译特性来绕过这个检查:目的是,达到在自己的其它类中直接来调用这些access$000()方法.
这样,我们可采用这个技术(即:在自己的类中--注意不是内部类,而是外部类中直接来调用这个access$000(Outer);)来访问其它类的private的数据成员了.
具体技术演示如下:
第一步:定义如下的类:
class Outer {
private final int xx = 123;
//由于是final,故不再自动生成access$000(Outer);
public Inner getInner() {
return new Inner();
}
public class Inner {
public int getDate() {
return xx;
}
} //class Inner
static int access$000(Outer)//这个是自已定义的!
{
return 1;
}
第二步:定义你的其它类,来直接调用这个access$000()方法
public class Test1
{
public static void main(String[] args)
{
System.out.println(Outer.access$000(new Outer())); //这个调用是没有问题的,因为是自己定义的!
}
}
将上述两个JAVA文件编译成class,成其是第二步的 Test1.class
第三步:这是变戏法的一步:
将第一步的类Outer改为如下:
class Outer {
private int xx = 123;
//由于不是final,故自动生成access$000(Outer);
public Inner getInner() {
return new Inner();
}
public class Inner {
public int getDate() {
return xx;
}
} //class Inner
/*将这个第一步中自己定义的access$000去掉,因为编译器会自动生成它!
static int access$000(Outer {
return 1;
} */
重新编译第三步中的这个类,而第二步中的类Test.class不动它. 此时,我们达到了这样一个目的:在类Test1中调用了Outer类中编译器自动生成的这个access$000(...)了.
----上篇借鉴别人的--
使用jd-gui反编译后去掉注释 /\*
*\d* *\*/
此处略作修改:\/\* *\d* *\*\/
去掉最后一行自动生成的注释 /\* Location:[\S\s]+?(?=\*/)\*/$
.access$ 反编译偶内部类调用外部类成员问题
很简单的一个测试类源码:
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);
}
}
可以看出,为了使内部类访问外部类的私有成员,编译器生成了形似 “外部类.access$XYZ”的函数。XYZ为数字。X是按照私有成员在内部类出现的顺序递增的。8是 service , YZ为02的话,标明是基本变量成员;YZ为00的话标明是对象成员或者函数,YZ为08的话标明是对象成员或者函数。
这些参数可以得出一张表对应表,等待整理
.....sionManager.access$102(..nManager.this, null);
相关文章推荐
- 反编译出现access$分析
- APK反编译jd-gui代码分析(草稿记录)
- 动力后台数据库说明|动力3.51后台数据说明|access数据分析说明
- php addslashes 函数详细分析说明
- Android 的 dex2jar 和 jd-gui 反编译 apk 源代码
- Android 的 dex2jar 和 jd-gui 反编译 apk 源代码
- 【移动安全】Android APK反编译(AXMLPrinter2,smali,dex2jar.bat,jd-gui.exe,baksmali)
- 脚本中出现 window.open() access is denied - 拒绝访问 情况一则及分析
- Oracle的分析函数(解析函数)说明
- Linux "零拷贝" sendfile函数中文说明及实际操作分析
- 【Android】使用dex2jar 与JD-Gui 反编译APK文件,查看源代码
- jd-gui反编译 access$xxx类函数说明
- 代码操作 ACCESS时为什么老出现XXX函数未定义错误?
- ORALCE分析函数 备注说明
- vc delphi 回调函数具体说明和实例与分析 - 转
- Oracle 分析函数(Analytic Functions) 说明
- Oracle分析函数、多维函数和Model函数简要说明,主要针对BI报表统计
- JAVA 反编译工具(JD-GUI)-查看源码利器
- Linux "零拷贝" sendfile函数中文说明及实际操作分析