在 Mac OS X 上,我可以通过运行以下命令找到运行 Java 程序的 HotSpot 探针:
cody.mello@ashur ~ (1) % sudo dtrace -ln 'hotspot*:::'
Password:
Invalid connection: com.apple.coresymbolicationd
ID PROVIDER MODULE FUNCTION NAME
165084 hotspot46 libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl(instanceKlassHandle, Thread*)] class-initialization-clinit
165085 hotspot46 libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl(instanceKlassHandle, Thread*)] class-initialization-concurrent
165086 hotspot46 libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl(instanceKlassHandle, Thread*)] class-initialization-end
165087 hotspot46 libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl(instanceKlassHandle, Thread*)] class-initialization-erroneous
165088 hotspot46 libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl(instanceKlassHandle, Thread*)] class-initialization-error
165089 hotspot46 libjvm.dylib _ZN13instanceKlass15initialize_implE19instanceKlassHandleP6Thread [instanceKlass::initialize_impl(instanceKlassHandle, Thread*)] class-initialization-recursive
...
但是如果我创建一个简单的 Java 程序并在 SmartOS 上运行它:
cody@101901c9-6d66-ea32-fe42-f1fbebd4bf99 ~ % cat Loop.java
class Loop {
public static void main(String[] args) throws InterruptedException {
while (true) {
Thread.sleep(5000);
}
}
}
cody@101901c9-6d66-ea32-fe42-f1fbebd4bf99 ~ % javac Loop.java
cody@101901c9-6d66-ea32-fe42-f1fbebd4bf99 ~ % java Loop
我找不到任何探测器:
cody@101901c9-6d66-ea32-fe42-f1fbebd4bf99 ~ (255) % pfexec dtrace -ln 'hotspot*:::'
ID PROVIDER MODULE FUNCTION NAME
dtrace: failed to match hotspot*:::: No probe matches description
我需要做什么特别的事情才能见到他们吗?
这里的问题是,在 SmartOS(以及其他 illumos 变体——以及它们专有的 Solaris 同类)上,JVM 中的 DTrace 模块是延迟加载(也就是说,DOF 是用-x lazyload
)。因此,在显式启用之前不会加载 DTrace 探针。有两种方法可以解决这个问题。第一个是您可以告诉 DTrace 本身启用有问题的特定探测器,强制目标进程加载其探测器。这需要(至少)目标进程的ID;为了在问题中提供的示例中表达这一点,它将类似于:
% pfexec dtrace -ln 'hotspot*$target:::' -p `pgrep -fn "java Loop"`
这将拾取hotspot
(and hotspot_jni
) USDT 探针,但仍然使用jstack()
在充满毫无戒心的 Java 进程的机器上执行此操作很困难。 (也就是说,当您想要在已知进程上使用 USDT 探针时,这才有效,而不是当您想要使用 ustack 帮助程序分析所有 Java 进程时。)如果这是您关心的问题,在 illumos 变体(SmartOS、 OmniOS 等),您可以通过使用审计库专为该任务而设计。这个图书馆——/usr/lib/dtrace/libdtrace_forceload.so
及其 64 位变体,/usr/lib/dtrace/64/libdtrace_forceload.so
-- 将有效地强制在进程启动时加载 DTrace 探针,为您提供 USDT 探针和jstack()
对所有此类流程采取行动。要对 32 位 JVM 执行此操作,请启动java
与LD_AUDIT_32
环境变量设置:
export LD_AUDIT_32=/usr/lib/dtrace/libdtrace_forceload.so
对于 64 位 JVM:
export LD_AUDIT_64=/usr/lib/dtrace/64/libdtrace_forceload.so
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)