【问题标题】:Different behavior between debug and normal execution mode - WeakReference handling调试和正常执行模式之间的不同行为 - 弱引用处理
【发布时间】:2018-07-18 23:16:18
【问题描述】:

我修补了java.lang.ref.Reference 类以在调用get() 时调用自定义本机方法。修补的类被添加到引导类路径中。

当我启动一个示例程序时,我看到很多打印输出来自我的本机方法(如预期的那样),因为 JDK 内部使用了很多 References。

奇怪的行为始于我的main 方法。我所做的只是为一个对象创建一个WeakReference,删除强对象并调用get()。无论出于何种原因,我添加的本机方法似乎都没有在运行模式下被调用,并且我没有得到任何打印输出或本机内部发生的其他事件。

如果我在调试模式下启动程序,一切都会按预期工作,即调用本机方法。

如果我将WeakReference 更改为SoftReference,它总是可以工作,在正常运行模式下也是如此。

我什至尝试添加其他代码(例如将System.out.println 添加到get()),但这也没有用。在非调试模式下运行时,我的WeakReference 的打印以某种方式停止。在调试中它总是有效的。

有时我什至会在我的主服务器关闭期间从Finalizers 收到很多事件/打印输出。所以看起来Reference 类的行为确实有所不同。

【问题讨论】:

  • 如果您包含一些代码示例,它可能会很有用。

标签: java debugging reference jvm


【解决方案1】:

java.lang.ref.Reference.get()JVM intrinsic method

这意味着一旦方法被 JIT 编译,它的 Java 实现就不再被调用。 HotSpot 编译器将调用 Reference.get 替换为特殊的手动优化序列 hardcoded in HotSpot sources

在 JVM 启动时,该方法还没有被 JIT 编译,即它的 Java 实现被解释,而内在函数不起作用。

SoftReference overrides 方法,所以 Reference.get 内在函数也不起作用。

您可以使用以下 JVM 标志禁用此内在函数,并且您的修改版本将始终有效,即使在该方法经过 JIT 编译后也是如此:

-XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_Reference_get

Here is the list JDK 中的其他内部方法。

【讨论】:

  • 你就是男人!不知道硬编码的内在函数,因此从我的考虑中排除了 JIT,因为我天真地认为“将被 JIT 编译,但逻辑将保留”。旗帜虽然不起作用。 -XX:DisableIntrinsic=_Reference_gethere 的建议都不是禁用所有。 -XX:CompileCommand="exclude java/lang/ref/Reference get" 虽然完成了这项工作,但我认为我最好使用 WeakReference 的子类并动态替换所有代码以使用该代码。谢谢!
  • @HaasipSatang 啊,对:-XX:DisableIntrinsic 禁用了 C2 内在函数,但该方法仍然被 C1 内在函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多