【问题标题】:Is it possible to start java jdwp after JVM startup (aka: at runtime) without command line parameters?是否可以在没有命令行参数的 JVM 启动后(又名:在运行时)启动 java jdwp?
【发布时间】:2021-06-04 01:55:51
【问题描述】:

我想在当前 JVM 上的某个时间点启用调试,而不添加命令行参数 -agentlib:jdwp

是否可以在当前运行的 JVM 中以编程方式执行此操作? 没有任何第三方库?

其他命令行参数(如-Djdk.attach.allowAttachSelf=true)可以考虑。

VirtualMachine vm = VirtualMachine.attach(Long.toString(ProcessHandle.current().pid()));
vm.loadAgentLibrary("jdwp", "transport=dt_socket,server=y,address=8000,suspend=n");

原因:

com.sun.tools.attach.AgentLoadException: Failed to load agent library: _Agent_OnAttach@12 is not available in jdwp

【问题讨论】:

  • 基本上,你自己回答了。 jdwp 代理不支持OnAttach,很可能是因为它需要只能在OnLoad 中激活的功能。
  • 确实如此,但这是因为技术问题还是仅仅是设计原则?可能有一些解决方法或(未知)替代方案
  • 不难想象,激活某些功能,尤其是调试器所需的功能,可能需要选择某些 JVM 功能的替代实现,这会影响性能,因此 JVM 在初始化时会根据请求的功能,之后无法更改。就像启动后无法更改垃圾收集器算法一样。
  • 它确实有影响,我同意。尽管您可以附加一个分析器/代理,它可以在运行时拦截、检查和重写类。我不知道调试器功能是如何设计或实现的,但是我(天真地)假设在断点处覆盖一个带有锁的类可以做到这一点。答案似乎是“不”(首先根据尝试),我只是希望我有一个技术原因。
  • 设置断点可以通过将代码热交换到在该点停止执行的东西来模拟,但热交换本身有其自身的局限性。已经运行的代码可能会继续使用旧代码,并且交换通常在生效之前可能会有很大的延迟。所以它不像“挂起线程”动作,它可能会在真正停止之前错过很多执行。它仍然不意味着检查或更改局部变量。您可以为此注入更多代码,但它不起作用,例如检查挂起的线程。

标签: java remote-debugging jdi jdwp


【解决方案1】:

在现代 JVM (Java 6+) 中,代理使用 JVM TI 接口。

JVM 工具接口 (JVM TI) 是开发和监控工具使用的编程接口。它提供了一种检查状态和控制在 Java 虚拟机 (VM) 中运行的应用程序执行的方法。

在 JVM TI 中,您必须启用所需的功能

功能函数允许您更改 JVM TI 可用的功能,即可以调用哪些 JVM TI 函数、可以生成哪些事件以及这些事件和函数可以提供哪些功能。

当(JVM 的哪个状态)取决于供应商时,可以添加哪些功能。 JDWP 只是 JVM 和调试器之间的调试协议。它只是像任何其他代理一样利用 JVM TI 的功能。同时,很可能只能在OnLoad 阶段(在大多数JVM 中)添加调试功能。 (即:can_generate_breakpoint_eventscan_suspend,...)

添加功能:通常在OnLoad 函数中使用此函数。某些虚拟机可能允许在实时阶段添加一组有限的功能。

这解释了为什么必须在 JVM 启动时声明 jdwp 代理才能为 JVM TI 添加适当的功能。

文档:https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#capability

感谢@Holger 指出方向。

【讨论】:

猜你喜欢
  • 2011-07-22
  • 2012-12-07
  • 1970-01-01
  • 2011-01-18
  • 2020-12-31
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2018-04-14
相关资源
最近更新 更多