2

我没有使用 java 应用程序的经验,但我发现找到指向这些应用程序内存地址的静态指针等通常(几乎)不可能,显然是因为处理代码的 java 引擎(如果这种命名方式,请纠正我)错了请)。

现在,我使用了 VisualVM ( https://visualvm.dev.java.net/ ),它很棒。我可以选择我的 java 进程并创建一个堆转储。然后它向我显示所有类及其值。

我可以使用这种方法不断轮询堆转储并接收对象值,例如游戏的 XY 和 Z?我将如何以编程方式与此类应用程序交互,如果这不应该使用 VisualVM 完成,还有什么替代方案?

编辑:这是我需要做的: 我需要能够找到所有具有特定值的属性的类。例如:我会搜索 X 坐标(一个浮点数),它应该返回类“PlayerCoordsHandler”(只是一个例子)和相应的浮点数及其值......或者只是一种再次找到这个相同浮点数的方法(例如重新启动后)。这个过程不必是编程的,只要请求现在已知的属性(x float)的值可以通过编程(例如使用命令行实用程序或从文件读取)来检索。

Edit2: 目标应用程序是 Windows 可执行文件(但使用 java 制作)并启动它自己的 java VM。无法添加用于调试的 java 参数。但这似乎不是必需的,因为 VirtualVM 能够很好地调试该过程。有谁知道怎么做?

提前致谢。

4

7 回答 7

3

看起来您想要调试正在运行的 Java 应用程序。

“官方”Java 调试器是 JDB。我相信它是JDK的一部分。它具有设置断点、检查堆、列出和显示甚至更改变量、显示正在运行的线程等功能。通常的调试器的东西。但它是命令行,使用起来让人头疼。

相反,使用带有集成调试器的 IDE 很有意义。我使用 Eclipse。您可以执行所有常见的调试操作,包括显示带有变量的窗口。您可以设置条件断点,还有更多。特别是在回答您的问题时,您可以设置监视表达式,该表达式将在程序执行期间进行评估,并且它们的显示会在它们发生变化时刷新为新值。

您可能不想在 IDE 中运行您的 Java 应用程序;或者它可能在 Web 应用程序服务器中运行。这对于 JDB 或 Eclipse(或其他 IDE,如 NetBeans 或 IntelliJ Idea)来说没有问题:它们可以连接到正在运行的 JVM 并以同样的便利级别进行远程调试。

像这样远程或以其他方式调试的程序运行速度比没有调试时要慢一些。您的游戏在被调试时会以相当糟糕的 FPS 运行;但它仍然应该或多或少地正常响应游戏交互。


远程调试:

为了能够将Eclipse NetBeans 调试器附加到正在运行的 Java 进程,您需要使用以下 Java 选项启动该进程……</p>

-Xdebug -Xrunjdwp:transport=dt_socket,address=3704,server=y,suspend=n
于 2010-01-07T11:32:11.920 回答
2

触发 heapdump 对于内存泄漏的事后分析很有用,但是随着 Java 垃圾收集器移动对象,您不能使用 heapdump 的内存值来可靠地访问这些对象。

如果您需要一种从应用程序外部查询内部值的方法,您可以考虑设置一个 RMI 服务 API,您可以通过该 API 检索您需要的值。

另一种方法(如果您只需要测试某些东西)可能是通过 de Java 调试 API 连接到进程。

如果您知道所使用的 JRE 位置,则可以重命名 java.exe 并编写一个 (C/C++) 包装器,该包装器添加 Carl 列出的调试选项并依次调用重命名的_java.exe。

另一种可能性可能是.jar在应用程序的文件中添加或更新类。您不需要源来执行此操作。

汤姆,你是否试图对一个专门试图混淆其工作的应用程序进行逆向工程?如果是这样,如果您联系制造商并询问他们他们认为您试图实现的目标有哪些可能性,您可能会走得更远?

于 2010-01-07T11:03:19.377 回答
2

看看YourKit。您可以实时监控 CPU、内存和线程,并随时生成转储。它甚至可以比较不同的内存转储,以显示添加/删除了哪些对象。

虽然它不是免费的,但它有 15 天(或 30 天?)的全功能评估期。如果免费不是一个真正的问题,它绝对是一个很棒的工具。

于 2010-01-07T11:05:56.270 回答
2

我很好的起点是Java 6 中添加的jps和工具(我认为)。为您提供每个应用程序的 pid 和 main 类。为您提供有关流程的更多详细信息jstatjpsjstat

于 2010-01-07T11:07:45.990 回答
2

您可以通过创建自己的与 JVM 的 JMX 连接来轻松生成堆转储,就像 VisualVM 所做的那样。分析 heapdump 是非常有可能的(数据在那里并且与 JVM 完全断开,因此没有来自 gc 的干扰)。

但是,除非您正在寻找一个非常具体的场景,否则最好将堆转储提供给MAT并在其中找到一个好的工作流程以供使用。

编辑:在这种特殊情况下,最好创建某种特定的 API 来从外部访问值(并可能使用 JMX 将值发布为 MBean)。如果您只想监视一些值,那么进行堆转储是一项很重要的工作。

Edit2:根据您的编辑,在我看来,您可以从通过 JMX 发布自己的 MBean 中真正受益。我必须跑去开会,但除非我不在的时候有其他人这样做,否则我会尽量记住稍后给你一些指示。无论是在此编辑中还是在新帖子中。

于 2010-01-07T11:08:36.300 回答
1

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

于 2010-01-07T11:06:48.407 回答
0

使用 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编写自定义日志记录

它是调试的替代方法。

于 2014-07-07T18:33:48.960 回答