首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么InvokeVirtual在调用class.NewInstance()时使用而不是InvokeSpecial?

为什么InvokeVirtual在调用class.NewInstance()时使用而不是InvokeSpecial?
EN

Stack Overflow用户
提问于 2017-03-05 15:25:15
回答 2查看 868关注 0票数 2

我正在研究以下java程序的反汇编问题

代码语言:javascript
复制
public class ASMPlayground {
    private String bar;

    public String getBar(){
        return bar;
    }

    public void setBar(String bar) throws IllegalAccessException, InstantiationException {
        String name = String.class.newInstance();
        System.out.println(name);
    }

    public static void main(String[] args) {

    }
}

下面的字节码片段吸引了我的眼球,看起来不太理想。

代码语言:javascript
复制
LDC Ljava/lang/String;.class
INVOKEVIRTUAL java/lang/Class.newInstance ()Ljava/lang/Object;
CHECKCAST java/lang/String

问题:

当要执行的方法依赖于对象引用时,将使用InvokeVirtual。既然“类”是最终的,而newInstance()只存在于“类”中,为什么不使用InvokeSpecial而不是InvokeVirtual呢?会不会更有表现力呢?

EN

回答 2

Stack Overflow用户

发布于 2017-03-05 16:28:36

InvokeSpecial用于指定以下调用

超类、私有和实例初始化方法调用

规格:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokespecial

Class.newInstance既不是超类方法调用,也不是私有方法调用,也不是调用初始化方法。它也不是一个动态的方法,InvokeDynamic在这里没有什么可做的。这两种指令都不能在这里使用,因为它将面对jvms。在创建jvms时,允许用“更好的”指令替代某些指令,但正如我在jvms中所看到的,它还没有完成。

会不会更有表现力呢?

JIT非常聪明,可以理解在这种情况下不需要遍历虚拟方法表,所以它不应该减慢执行速度。实际的性能应该通过实际的测试来比较,但是我认为没有理由期望有显著的差异。

票数 3
EN

Stack Overflow用户

发布于 2017-03-06 09:19:08

目标方法或类是final这一事实不会使用另一个类/调用该方法来更改已编译的类的形式。

这是JLS第13章规定的。“二进制兼容性”, methods

将声明为final的方法更改为不再声明为final并不会破坏与现有二进制文件的兼容性。

同样地, Classes

将声明为final的类更改为不再声明为final并不会破坏与现有二进制文件的兼容性。

显然,依赖于目标方法的final性质的调用指令将违反此规范。

没有预期的相关性能影响。当符号引用必须解析到实际方法时(根据JVM的运行时表示),总是存在第一次开销。此时,JVM还可以记录这个方法或它的声明类实际上是调用指令的final (如果有好处的话)。现代JVM甚至更进一步,例如,利用一个非final方法实际上没有被覆盖的事实,尽管如果一个子类被加载和实例化(它有一个覆盖的方法),则需要对这些调用进行去优化。因此,唯一的区别是,final修饰符可以保证这样的去优化是不必要的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42610150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档