java - 在 Java 中运行时省略实例字段

标签 java jvm metaprogramming jvm-hotspot

Java 的断言机制允许禁用断言,如果断言被禁用,则断言基本上没有运行时成本(除了更大的类文件)。但这可能涵盖所有情况。

例如,许多 Java 集合都具有“快速失败”迭代器,它们会尝试检测您何时以线程不安全的方式使用它们。但这需要集合和迭代器本身来维护额外的状态,如果不存在这些检查,则不需要这些状态。

假设有人想做类似的事情,但允许禁用检查,如果禁用它们,它会在迭代器中保存一些字节,同样在 ArrayList 中保存更多字节,或者其他。

或者,假设我们正在做某种对象池,我们希望能够在运行时打开和关闭它;当它关闭时,它应该只使用 Java 的垃圾收集,并且不占用引用计数的空间,如下所示(请注意,编写的代码非常糟糕):

class MyClass {
    static final boolean useRefCounts = my.global.Utils.useRefCounts();
    static {
        if(useRefCounts)
            int refCount; // want instance field, not local variable
    }
    void incrementRefCount(){
        if(useRefCounts) refCount++; // only use field if it exists;
    }
    /**return true if ready to be collected and reused*/
    boolean decrementAndTestRefCount(){
        // rely on Java's garbage collector if ref counting is disabled.
        return useRefCounts && --refCount == 0;
    }
}

上面代码的问题是静态 block 没有意义。但是有没有一些技巧可以使用低功率魔法来使这些东西发挥作用呢? (如果允许使用高能魔法,核心选项是生成 MyClass 的两个版本,并安排在启动时将正确的版本放在类路径上。)

最佳答案

注意:您可能根本不需要这样做。 JIT 非常擅长内联运行时已知的常量,尤其是 boolean 值,并优化掉未使用的代码。

int 字段并不理想,但是,如果您使用的是 64 位 JVM,则对象大小可能不会改变。

在 OpenJDK/Oracle JVM(64 位)上, header 默认为 12 字节。对象对齐为 8 字节,因此对象将使用 16 字节。该字段增加了 4 个字节,对齐后也是 16 个字节。


要回答这个问题,您需要两个类(除非您使用生成的代码或 hack)

class MyClass {
    static final boolean useRefCounts = my.global.Utils.useRefCounts();

    public static MyClass create() {
        return useRefCounts ? new MyClassPlus() : new MyClass();
    }

    void incrementRefCount() {
    }

    boolean decrementAndTestRefCount() {
        return false;
    }
}

class MyClassPlus extends MyClass {
    int refCount; // want instance field, not local variable

    void incrementRefCount() {
        refCount++; // only use field if it exists;
    }

    boolean decrementAndTestRefCount() {
        return --refCount == 0;
    }
}

关于java - 在 Java 中运行时省略实例字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52487415/

相关文章:

java - 如何参数化 Web 应用程序(不是 servlet)的初始化

java - 休息服务: how to produce human readable output using XML + XSLT?

java - StandardReflectionParameterNameDiscoverer 如何编译到 jdk 版本 50?

java - 安卓工作室 : Failed to load JVM DLL

metaprogramming - 如何动态添加类属性?

ruby - 如何像调用实例方法一样动态调用模块方法?

java - (错误位置未知): 'basePropertyType 的重复变量声明

使用tomcat启动spring boot应用程序时出现java.lang.VerifyError

ruby - 动态创建一个没有命名空间的类

java - Quartz调度程序cron表达式超过1周