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/