我修补了java.lang.ref.Reference
类,以便在每次调用get()
时调用自定义本机方法。修补的类放在引导类路径的前面。
启动示例程序时,由于JDK内部使用了许多Reference
,因此我看到了很多打印输出来自本机方法(正如预期的那样)。
奇怪的行为始于我的main
方法。我要做的就是为对象创建WeakReference
,删除强对象并调用get()
。无论出于何种原因,我添加的本机方法似乎都不会在运行模式下被调用,并且我没有得到任何打印输出或本机内部发生的其他事件。
如果我以调试模式启动程序,那么一切都会按预期工作,即调用本机方法。
如果我将WeakReference
更改为SoftReference
,则它始终可以正常运行模式下运行。
我什至尝试添加其他代码(例如将System.out.println
添加到get()
),但这也没有用。在非调试模式下运行时,我的WeakReference
的打印会以某种方式停止。在调试中,它始终有效。
有时候,在关闭主机后的Finalizer
中,我什至会收到很多事件/打印输出。因此,看来Reference
类的行为似乎有所不同。
答案 0 :(得分:5)
java.lang.ref.Reference.get()
是JVM intrinsic method。
这意味着,一旦对方法进行了JIT编译,就不再调用其Java实现。 HotSpot编译器使用特殊的手动优化序列hardcoded in HotSpot sources替换了对Reference.get
的调用。
在JVM启动时,该方法尚未进行JIT编译,即该方法的Java实现已被解释,并且固有方法不起作用。
SoftReference
overrides该方法,因此Reference.get
内在函数也不适用。
您可以使用以下JVM标志禁用此内在函数,即使方法是JIT编译的,修改后的版本也将始终有效:
-XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_Reference_get
Here is the list在JDK中的其他内部方法。