美文网首页
如何减少dex/class文件中生成的access$x00方法

如何减少dex/class文件中生成的access$x00方法

作者: 扑扑兔 | 来源:发表于2019-01-24 20:53 被阅读17次

在安卓开发中,我们可能会经常遇到一些线上报错,显示access$x00方法报错,而实际上我们的代码中并没有这个方法。那么这些方法是怎么生成的呢?

实际上这些方法是由编译器自动生成的,举个例子,当我们在匿名内部类中试图访问外部类的private字段或方法时,此时,我们的内部类实际上并没有这些private字段或方法的访问权限。编译器此时会帮我们生成一个包访问权限的access$x00方法,通过这个方法我们就可以间接访问到类的private字段或方法

例如:以下java类

import android.widget.TextView;

public class ItemsView {

    private static String displayText(String item) {
    
         return ""; // TODO
    
    }
    
    private class ItemsAdapter {
    
        void bindItem(TextView tv, String item) {

            tv.setText(ItemsView.displayText(item));

        }

    }

} 

当我们运行

-- javac -bootclasspath %ANDROID_HOME%/platforms/android-24/android.jar ItemsView.java

-- javap -c ItemsView$ItemsAdapter

后,看到生成了如下的字节码文件

class ItemsView$ItemsAdapter {

  final ItemsView this$0;

  void bindItem(android.widget.TextView, java.lang.String);

    Code:

    0: aload_1

    1: aload_2

    2: invokestatic  #3   // Method ItemsView.access$000:(Ljava/lang/String;)Ljava/lang/String;

    5: invokevirtual #4   // Method android/widget/TextView.setText:(Ljava/lang/CharSequence;)V

    8: return

}

其中在Code 2:处,可以看到编译器帮我们生成了access$000代码。

那么如果我们想要去掉这些方法,该怎么做呢?

-- 将从内部类中调用的外部类的这些private 字段或方法,去掉private限定符即可。

去掉private限定符之后,再次运行

-- javap -c ItemsView$ItemsAdapter

得到如下结果,可以看到在Code 2:处,内部类中直接访问了外部类的方法

class ItemsView$ItemsAdapter {

    final ItemsView this$0;
    
    void bindItem(android.widget.TextView, java.lang.String);
    
    Code:
    
    0: aload_1
    
    1: aload_2
    
    2: invokestatic #3 // Method ItemsView.displayText:(Ljava/lang/String;)Ljava/lang/String;
    
    5: invokevirtual #4 // Method android/widget/TextView.setText:(Ljava/lang/CharSequence;)V
    
    8: return

}

实际用例


在笔者尝试通过修改限定符,减少access方法的实践中,发现涉及到一些Context的access引用访问,一时找不到具体定义。通过反复查看代码,思考,修改,测试,最终找到相关引用链

Context是由基类引入,例如在BaseActivity中,将Context的限定符设置为protected,此时BaseActivity的子类可以直接引用Context。如果此时子类的内部类也想访问这个Context引用呢,那么这个Context引用相对于这个子类的内部类,它是protected,还是private?

实际上当我将父类的Context限定符修改为public时,从子类的内部类中访问该Context引用时,不会生成access$x00方法;

而当Context的限定符为protected时,从子类的内部类中访问该Context引用时,生成了access$x00方法。

所以,关于这个疑问“此时Context引用相对于这个子类的内部类,它是protected,还是private?”,我的答案是private。

用例的正确解答


在仔细思考、验证之后,发现是否生成access方法,并不是猜测的

--“此时Context引用相对于这个子类的内部类,它是protected,还是private?”,我的答案是private

而是与子类和父类是否放置在同一包名下有关,在同一包名下,由protected限定符的含义,不管是否子类都可以访问,而当子类与父类不在同一包名下时,只有子类可以访问父类的protected方法/字段,子类的内部类则不能直接访问父类的protected方法/字段。

有兴趣的读者,可以自行测试

参考资料:探索 Java 隐藏的开销

相关文章

  • 如何减少dex/class文件中生成的access$x00方法

    在安卓开发中,我们可能会经常遇到一些线上报错,显示access$x00方法报错,而实际上我们的代码中并没有这个方法...

  • 热修复与插件化基础——dex与class

    一、dex/class浅析 1、class与dex对比 2、生成class与dex文件的指令 生成并运行class...

  • 32. 热修复-QQ空间超级补丁方案

    .class生成dex 注:在我们测试过程中,需要将class生成dex文件,这个生成的过程很烦人,可能会出现绝对...

  • dex文件与class文件如何生成

    一、dex文件与class文件如何生成Class文件:可以被JVM所识别的文件。记录一个类文件的所有信息。文件结构...

  • Gradle transform api 简介

    前言 在打包流程中,我们知道生成.class文件后,利用dx工具生成.dex文件,而利用Transform API...

  • frida调用制作的dex

    一、如何制作dex 通常我们需要将某些代码逻辑包含在某个class中,写好class后,怎样将其制作成dex文件?...

  • android打包流程

    summary 编译src文件,生成class文件 将class文件编译成为dex文件 编译资源文件(不包括ass...

  • 记一次dx.bat 错误

    今天于as中,使用.class文件生成.dex 文件时,出错 一: 不能执行的愿原因是,jdk版本太高,我直接还原...

  • 手动构建apk

    aapt 编译R文件 javac 将java文件生成.class文件 dex 编译资源,将 res下面的资源打...

  • Android热修复【实战一】

    说了那么多的原理,也该手写撸撸代码去实现一下。 1、生成Dex文件 将class文件打包成dex文件 1.1 dx...

网友评论

      本文标题:如何减少dex/class文件中生成的access$x00方法

      本文链接:https://www.haomeiwen.com/subject/nenujqtx.html