Java编译器自动生成access$xxx方法探究

简介

Java编译器在编译过程中自动生成accessxxx方法,主要是为了内部类与外部类私有成员的访问,又不愿破坏类的封装性,所以就在被调用类中生成package权限静态的accessxxx方法

实例

接下来,我们就看看那些情况会生成accessxxx方法,还有就是accessxxx方法有啥特点

情况一

私有内部类访问外部类私有成员变量,源代码如下

public class OutClass extends Base {
    private String test = "test";
    String test2 = "test";
    private String test3 = "test";

    private class InnerClass {
        private InnerClass() {
        }

        public void innerTest() {
            String test = OutClass.this.test;
            String test2 = OutClass.this.test2;
            String test3 = OutClass.this.test3;
            String baseTest = OutClass.this.baseTest;
            outTest();
            outTest2();
            outTest3();
            baseTest();
        }
    }

    private void outTest() {
    }

    void outTest2() {
    }

    public void outTest3() {
    }
}

首先看一下编译后外部类字节码,通过javap -c查看

public class OutClass extends Base {
  java.lang.String test2;

  public sort.OutClass();
    Code:
       0: aload_0
       1: invokespecial #4                  // Method sort/Base."<init>":()V
       4: aload_0
       5: ldc           #5                  // String test
       7: putfield      #3                  // Field test:Ljava/lang/String;
      10: aload_0
      11: ldc           #5                  // String test
      13: putfield      #6                  // Field test2:Ljava/lang/String;
      16: aload_0
      17: ldc           #5                  // String test
      19: putfield      #2                  // Field test3:Ljava/lang/String;
      22: return

  void outTest2();
    Code:
       0: return

  public void outTest3();
    Code:
       0: return

  static java.lang.String access$000(sort.OutClass);
   flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
       0: aload_0
       1: getfield      #3                  // Field test:Ljava/lang/String;
       4: areturn

  static java.lang.String access$100(sort.OutClass);
   flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
       0: aload_0
       1: getfield      #2                  // Field test3:Ljava/lang/String;
       4: areturn

  static void access$200(sort.OutClass);
   flags: ACC_STATIC, ACC_SYNTHETIC
    Code:
       0: aload_0
       1: invokespecial #1                  // Method outTest:()V
       4: return
}

看到外部类的中多了access000和access100方法以及没有内部类,而在目录中会多一个OutClassInnerClass.class文件,接下来看OutClassInnerClass.class

class OutClass$InnerClass {
    private OutClass$InnerClass(OutClass var1) {
        this.this$0 = var1;
    }

    public void innerTest() {
        String test = OutClass.access$000(this.this$0);
        String test2 = this.this$0.test2;
        String test3 = OutClass.access$100(this.this$0);
        String baseTest = this.this$0.baseTest;
        OutClass.access$200(this.this$0);
        this.this$0.outTest2();
        this.this$0.outTest3();
        this.this$0.baseTest();
    }
}

类的访问权限会被由private修改成default,test方法中调用外部类的私有成员变成对了OutClass.accessxxx(this.this0)方法的调用

情况二

外部类调用内部类私有成员

public class sort.OutClass {
  public sort.OutClass();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void outTest();
    Code:
       0: new           #2                  // class sort/OutClass$InnerClass
       3: dup
       4: aload_0
       5: aconst_null
       6: invokespecial #3                  // Method sort/OutClass$InnerClass."<init>":(Lsort/OutClass;Lsort/OutClass$1;)V
       9: astore_1
      10: aload_1
      11: invokestatic  #4                  // Method sort/OutClass$InnerClass.access$100:(Lsort/OutClass$InnerClass;)Ljava/lang/String;
      14: astore_2
      15: aload_1
      16: getfield      #5                  // Field sort/OutClass$InnerClass.test2:Ljava/lang/String;
      19: astore_3
      20: aload_1
      21: invokestatic  #6                  // Method sort/OutClass$InnerClass.access$200:(Lsort/OutClass$InnerClass;)Ljava/lang/String;
      24: astore        4
      26: aload_1
      27: getfield      #7                  // Field sort/OutClass$InnerClass.baseTest:Ljava/lang/String;
      30: astore        5
      32: aload_1
      33: invokevirtual #8                  // Method sort/OutClass$InnerClass.innerTest:()V
      36: aload_1
      37: invokestatic  #9                  // Method sort/OutClass$InnerClass.access$300:(Lsort/OutClass$InnerClass;)V
      40: aload_1
      41: invokevirtual #10                 // Method sort/OutClass$InnerClass.innerTest3:()V
      44: aload_1
      45: invokevirtual #11                 // Method sort/OutClass$InnerClass.baseTest:()V
      48: return
}

外部类调用内部类私有成员内部类也会生成access$xxx方法

总结

accessxxx方法只有在内部类、外部类访问对方私有成员时java编译器才会生成,accessxxx方法flag是ACC_STATIC、 ACC_SYNTHETIC,ACC_STATIC是指静态方法,ACC_SYNTHETIC是指此方法是编译器生成的。调用asscess方法要比直接使用变量消耗性能,大量的access方法会对性能有一些影响。另外,在Android中art以及dalvik虚拟机执行的是dex文件,dex中方法数不能超过64K,编译器多生成的access方法,意味着可能要多分几个dex包,意味着会增加包的体积,同样也会增加虚拟机加载dex时间,造成冷启动启动时间延长。<P>
如何减少access方法生成呢?主要有两个方案。

  • 方案一:开发者开发时把访问权限改成default,这个显然有点难度
  • 方案二:通过asm查找并删除flags标记为ACC_STATIC、 ACC_SYNTHETIC,前缀为access的方法
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容