VisualVM这样的软件的替代品,通过搜索堆转储以编程方式查找正在运行的Java应用程序的值等?

j9per5c4  于 2023-01-24  发布在  Java
关注(0)|答案(8)|浏览(134)

我对java应用程序没有经验,但我发现找到指向这些应用程序内存地址的静态指针等通常(几乎)是不可能的,显然是因为处理代码的java引擎(如果这种命名方式是错误的,请纠正我)。
现在,我已经使用了VisualVM(https://visualvm.dev.java.net/),它非常棒。我可以选择我的java进程并创建一个堆转储。然后它会向我显示所有的类和它们的值。
我可以使用这个方法来持续轮询堆转储并接收对象值吗?例如游戏的X、Y和Z?我将如何以编程方式与这样的应用程序交互,如果不应该使用VisualVM来完成,有什么替代方法吗?

    • 编辑:这是我需要做的:**我需要能够找到所有属性具有某个值的类。例如:我会搜索X坐标(浮点型),并且它应该返回类"PlayerCoordsHandler"(只是一个示例)和相应的浮点数及其值...或者只是一种再次查找相同浮点数的方法(例如在重新启动之后)。该过程不必是编程的,只要请求现在已知的属性(X浮点)的值就可以通过编程来检索(例如,利用命令行实用程序或从文件读取)。
    • Edit2:**目标应用程序是一个windows可执行文件(但使用java制作),并启动它自己的java VM。不可能添加java参数进行调试。但这似乎不是必需的,因为VirtualVM能够很好地调试进程。有人知道怎么做吗?

先谢了。

9lowa7mx

9lowa7mx1#

看起来您需要调试正在运行的Java应用程序。
“官方的”Java调试器是JDB。我相信它是JDK的一部分。它有能力设置断点,检查堆,列出和显示甚至改变变量,显示正在运行的线程等等。常见的调试器的东西。但它是命令行,这使得它很难使用。
相反,使用集成调试器的IDE更有意义。我使用Eclipse。您可以执行所有常见的调试操作,包括显示带有变量的窗口。您可以设置条件断点,还有很多其他操作。具体回答您的问题,您可以设置监视表达式,这些表达式将在程序执行期间进行计算,并且当它们发生变化时,它们的显示将用新值刷新。
您可能不希望在IDE内部运行Java应用程序;或者它可能运行在Web应用服务器上,这对JDB或Eclipse(或其他IDE,如NetBeans或IntelliJ Idea)来说没有问题:他们可以连接到正在运行的JVM,并以同样的方便程度进行远程调试。
像这样被调试的程序,不管是远程的还是其他的,运行起来都会比没有调试时慢一些。你的游戏,在调试的时候,会以相当难看的FPS运行;但是它仍然应该或多或少地正常响应游戏交互。

远程调试:

要将EclipseNetBeans调试器连接到正在运行的Java进程,您需要使用以下Java选项启动该进程...

-Xdebug -Xrunjdwp:transport=dt_socket,address=3704,server=y,suspend=n
xt0899hw

xt0899hw2#

看看YourKit,你可以实时监控CPU、内存和线程,并随时生成转储,它甚至可以比较不同的内存转储,以显示添加/删除了哪些对象。
它不是免费的,它有一个15天(或30天?)的全功能评估期。如果免费不是一个真实的的关注,它肯定是一个伟大的工具。

13z8s7eq

13z8s7eq3#

一个好的起点是Java 6中添加的jpsjstat工具(我认为)。jps为您提供了每个应用程序的pid和主类。jstat为您提供了有关进程的更多细节

50few1ms

50few1ms4#

触发堆转储对于内存泄漏之类的事后分析非常有用,但是当Java垃圾收集器移动对象时,您无法使用堆转储的内存值来可靠地访问这些对象。
如果您需要一种从应用程序外部查询内部值的方法,您可以考虑设置一个RMI服务API,通过它可以检索所需的值。
另一种方法(如果您只是需要测试某些东西)可以是通过Java调试API连接到进程。
如果您知道所使用的JRE位置,则可以重命名java. exe并编写一个(C/C++) Package 器,该 Package 器添加Carl列出的调试选项并依次调用renamed_java. exe。
另一种可能性是在应用程序的.jar文件中添加或更新类。您不需要源代码来执行此操作。
汤姆,你是不是在试图对一个应用程序进行反向工程,特别是试图混淆它的工作?如果是这样,你可能会得到更进一步,如果你联系制造商,问他们有什么可能性,他们看到你试图实现什么?

f5emj3cl

f5emj3cl5#

您可以通过创建自己的JMX连接到JVM来轻松地生成堆转储,就像VisualVM所做的那样。分析堆转储是非常可能的(数据就在那里,并且与JVM完全断开,因此没有来自gc的干扰)。
但是,除非您正在寻找一个非常具体的场景,否则最好将堆转储交给MAT,并在那里找到一个好的工作流来使用。

**编辑:**在这种特殊情况下,创建某种特定的API来从外部访问值可能会更好(并且可能使用JMX将值发布为MBean)。如果您只想监视几个值,那么使用堆转储会有很多工作要做。
**Edit2:**基于您的编辑,我认为您可以从通过JMX发布自己的MBean中获益。我必须赶去参加一个会议,但是,除非有人在我不在的时候做这件事,否则我会尽量记住稍后给予您一些提示。无论是在本文的编辑中还是在新帖子中。

h22fl7wq

h22fl7wq6#

如果您想在Java应用程序运行时轮询特定对象的值,您可能会发现使用JMX比使用堆转储更好、更有效。使用JMX,您可以定义应该公开哪些值,并使用VisualVM或JConsole等工具在运行时查看这些值。

5q4ezhmt

5q4ezhmt7#

使用VisualVM和heapdump,您可以通过OQL找到所有具有特定属性的类:

var out = "";
var cls = filter(heap.classes(), "/java./(it.name)")

while (cls.hasNext()) {
  var cl = cls.next();
  var fls = cl.fields;
  while (fls.hasMoreElements()) {
    var fl = fls.nextElement();
    if (/size/(fl.name)) {
      out = toHtml(cl) + "." + fl.name + "()\n";
    }
  }
}

out.toString()

并为BTrace编写自定义日志
它是调试的备选方案。

v09wglhw

v09wglhw8#

聚变React堆可能是一个很好的替代方案。
VisualVM并没有给予你很多应用程序内存的内部信息,除了总的堆分配。堆是一个很好的开始指标,但我觉得这不足以解决内存相关问题的实际原因。
FusionReactor将显示它检测到的所有内存空间,这取决于您运行的Java版本:
堆分配非堆分配CodeHeap(已分析和未分析的方法)压缩类空间FusionReactor还显示了每一代占用的内存量Eden Space旧空间Survivor Space
https://www.fusion-reactor.com/blog/java-visualvm-alternatives/

相关问题