views:

557

answers:

6

I'm not experienced with java applications but I found out that finding static pointers etc. to these applications' memory addresses is often (nearly) impossible, apparently because of the java engine that handles the code (correct me if this way of naming it is wrong please).

Now, I've used VisualVM (https://visualvm.dev.java.net/) and it's great. I can select my java process and create a heap dump. It then shows me all classes and their values.

Can I use this method to continousely poll the heap dump and receive object values, for example the X Y and Z of a game? How would I programmatically interact with such application, and if this should not be done with VisualVM, what would be an alternative?

Edit: this is what I need to do: I need to be able to find all classes with properties that have a certain value. For example: I'd search for the X coordinate (a float) and it should return the class "PlayerCoordsHandler" (just an example) and the corresponding float with it's value... or alternatively just a way to find this same float again (after restarting for example). This process does not have to be programmatic, aslong as requesting the value of the now known property (x float) can be retrieved programmatically (for example with a command line utility or reading from a file).

Edit2: The target application is a windows executable (but made with java) and launches it's own java VM. It's not possible to add java parameters for debugging. This does not seem to be required though, as VirtualVM is able to debug the process just fine. Anyone knows how?

Thanks in advance.

+2  A: 

Triggering a heapdump is usefull for post-mortem analysis of say memory leaks, but as the Java garbage collector moves objects around, you cannot use the memory values of a heapdump to reliably access those objects.

If you need a way to query internal values from outside of the application you could look into setting up an RMI service API via which you can retrieve the values you need.

Another method (if you just need to test something) could be to connect to the process via de Java debugging API.

If you know the JRE location that is used, you could rename java.exe and write a (C/C++) wrapper that adds the debug options listed by Carl and calls the renamed_java.exe in turn.

Another posibility might be to add or update classes in the .jar file of the application. You do not need the source to do this.

Tom, are you trying to reverse engineer an application that specifically tries to obfuscate its working? If so you might get further if you contact the manufacturer and ask them what possibilities they see for what you try to achieve?

rsp
Just to help Tom and me keep track of which solutions are in the running: I'm afraid recent updates of his have put RMI out of the question (no source to muck with) and remote debugging (probably) too (no access to the JVM command line).
Carl Smotricz
Unfortunately the app runs fine when the java exes are removed. There is also no java process active, and I can't find a java service either. However, the java.dll file in the JRE folder is used and visualVM can see the application. It also verifies that my JRE folder location is correct, it just doesn't seem to be using the java executables.
Tom
+1  A: 

Have a look at YourKit. You can monitor CPU, memory and threads live, and generate dumps whenever you want. It can even compare different memory dumps to show you which objects were added/removed.

It's not free though, it has a 15 day (or 30 day?) fully functional eval period. If free is not a real concern it's definitely a great tool.

extraneon
+1  A: 

If you want to poll the values of specific objects while your Java application is running you would probably find that using JMX is a better and more efficient approach rather than using a heap dump. With JMX you can define what values should be exposed and use tools such as VisualVM or JConsole to view them at runtime.

Mark
Can this be done without access to source?
Carl Smotricz
I'm not sure. Depends on whether the application has an API available to access what you need. I guess you could create MBeans to call the API but there could be an issues with registering the MBeans on startup. You would probably need to create your own Java code to do this then launch the existing application. Again, no idea if this is possible without knowing what he does have to work with.
Mark
+1  A: 

I good starting point is the jps and jstat tools added in Java 6 (i think). jps gives you the pid and main class for each application. jstat give you more details about process

n002213f
+1  A: 

You can easily generate a heap dump by creating your own JMX connection to the JVM, just like VisualVM does it. Analyzing the heapdump is very possible (the data is there and totally disconnected from the JVM so there is no interference from the gc).

However, unless it is a very specific scenario you are looking for you are probably much better off giving the heapdump to MAT and find a good workflow in there to use.

Edit: In this particular case it is probably better to create some kind of specific API to access the values from the outside (and maybe publish the values as MBeans using JMX). Taking a heap dump is way to much work if all you want to do is monitoring a few values.

Edit2: Based on your edits, it seems to me like you could really benefit from publishing your own MBean over JMX. I have to run for a meeting but, unless someone else does it while I am away, I will try to remember to give you some pointers later. Either in an edit of this one or in a new post.

Fredrik
That'd be great. I indeed only want to monitor values. I'd appreciate help on how to do the MBean over JMX approach to receive values from the outside of an application connected to a JVM.
Tom
With from the outside I mean that it's not my application, but still on the same system of course. I don't have to access a different remote connection or something, if that is why you want to use JMX. If not, please ignore this message.
Tom
@Tom, let me see if I get it right. The application you want to monitor is not yours but still you know enough about its inner workings to look at variable values? It could very well be doable even if it is not your app but I wonder if it is worth the effort.
Fredrik
I think you got that right. For example a game will always have a player object (well most of them). One could retreive the coordinate parameters (values) of this object from the JVM and use it to automate things within the game. I just need to be able to search for values and then access that object's values all the time. By looking at what VisualVM can do, that seems possible. Normally one would use static pointers for memory addresses. However, because of the JVM this does not seem to be possible.
Tom
+1  A: 

It looks like you want to debug running Java applications.

The "official" Java debugger is JDB. I believe it's part of the JDK. It has the ability to set breakpoints, examine heaps, list and display and even change variables, show running threads and so on. The usual debugger stuff. But it's command line, which makes it a pain in the neck to work with.

Instead, it makes a lot of sense to use an IDE with integrated debugger. I use Eclipse. You can do all the usual debuggery things, including displaying windows with variables. You can set conditional breakpoints and there's much more. Specifically in answer to your question, you can set up watch expressions, which will be evaluated during the program's execution and their displays refreshed with new values when they change.

You may not want to run your Java app inside the IDE; or it may be running in a Web application server. That's no problem for JDB or Eclipse (or other IDEs, like NetBeans or IntelliJ Idea): They can connect to a running JVM and debug remotely with the same level of convenience.

A program being debugged like this, remotely or otherwise, run somewhat more slowly than if it were not. Your game, while being debugged, will run at rather bad-looking FPS; but it should still respond more or less normally to gameplay interaction.


Remote debugging:

To be able to attach your EclipseNetBeans debugger to a running Java process you need to start that process with the following Java options…

-Xdebug -Xrunjdwp:transport=dt_socket,address=3704,server=y,suspend=n
Carl Smotricz
Alright, it seems like I shouldn't use heap dumps but use these debugging tools to access the values directly. I will try to do this with the proposed applications. Would there be a way to automate this and retreive the output from command line or a text file?
Tom
Yes. As JDP is a command line utility reading commands from standard input I would think you'd be able to automate its operation. I don't have any experience with this, though.
Carl Smotricz
Update: For the requirement stated in the update to your question, you may need some programmatic help. i.e. If you could set up a static or at least unique object inside your game code that knows to find those other objects you're looking for and then have references to them in fields of its own, then the debugging part of the task will be much, much easier.
Carl Smotricz
I read at http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/jdb.html : "Another way to use jdb is by attaching it to a Java VM that is already running. A VM that is to be debugged with jdb must be started with the following options: ..." The application is not run with these parameters and I cannot do so either. Is that a problem?
Tom
@ Carl's update: Unfortunately I do not have access to the application's source.
Tom
Just tried debugging with NetBeans. It returns: "Attaching to pid=3704Not a debuggee, or not listening for debugger to attach". It is indeed not a debugger and I can not set it to be one if I do not own the source, right? How does VisualVM manage to debug it regardless?
Tom
That part is easy, my latest update tells how.
Carl Smotricz
Hey Carl, afraid you missed the "The application is not run with these parameters and I cannot do so either"-part. I am not launching this application manually, it's actually a windows executable using C++, java and other things combined. With VisualVM I can simply select the process and it does the job without adding any parameters.
Tom
Oh I see. This is starting to look non-trivial. You could probably still trick it by removing the "real" `java` from the classpath and replacing it with a `java.cmd` or `java.bat` that calls the real one with the required options. But if that don't work I'm afraid it would be time to give up on this approach. :(
Carl Smotricz
I'm sorry for not mentioning this earlier. Didn't think it was relevant because VirtualVM can simply debug the app. Too bad it's only creating heap dumps. Maybe that's why. I'm afraid I have no idea how to trick it the way you're suggesting either. Thanks a lot for all the help though.
Tom
Do make a serious attempt at running a "fake" Java. I just remembered that it's possible to command-line inject a "startup" class from outside a Java program, and if it could be done this would open the door to all kinds of kinky debug assists.
Carl Smotricz
I do not see any java files though (it's all bundled into an .exe, so not accepting any java specific parameters). I do know the location of the JRE the application is using, does that help?
Tom
Yes. I sure hope I'm not wasting your time on a wild goose chase. The idea is, remove that JRE's `java.exe` and `javaw.exe` from system PATH (you could just rename them if you wanna be brutal) and put a `java.CMD` and `javaw.CMD` file on the path that will call the renamed java `exe`s under the new name. If you can get that working you've got Java by the tail. I keep mentioning both java.exe and javaw.exe cause your app could be using either. Javaw is normally for GUI apps.
Carl Smotricz
Well the application is calling java.exe and not java.CMD. I can not modify it to call java.CMD instead of java.exe right?
Tom
Update: it appears that java.exe and javaw.exe are not used at all as the game runs fine after deleting them. Java.dll is in use however, not sure about other files.
Tom
Update2: client/jvm.dll is also being used. How would one process parameters to the JVM when it's not launched by an executable but loaded into the application with DLLs?
Tom
Honest answer: I'm out of my depth and give up. Sorry!
Carl Smotricz
No problem. :P I am at that stage too. Thanks for the help.
Tom