Monitor jvm heap size from C++ - java

Is there a way to programmatically get the current jvm stats such as classes loaded or current heap size from C++? I know there are many tools to do so but I would like to integrate this with another application that would read these statistics from time to time.

You can have a look at JVMTI and JNI.
JVMTI allows you to attach a native agent to a Java application, with loads of low-level functionalities like heap traversals, etc. It also contains "Garbage Collection Start" & "Garbage Collection Finish" events, which could be used as starting points.
JNI allows you to call Java functions from native code (and vic-versa). I could imagine that you could use this technique to obtain information from ManagementFactory or some similar Java class that provides the needed information. This post contains a complete example on how to call static Java methods via JNI, which should be a good starting point.

Related

Limiting memory usage of a Java/Rhino/Nashorn object

I'm extending a server application written in Java to allow user-defined callbacks (written in Javascript) to be run in response to requests. I've done some reading, and while it seems possible to disable Java classes in Nashorn, there is nothing stopping a user from creating Javascript code that allocates an enormous array without using any Java APIs. I'm wondering if there is any way to restrict this, either proactively or reactively.
The solution I came up with is to have a process pool of JVMs with small max heap sizes, which are responsible for running the user-defined code. There will be a worker pool manager to spawn new processes when needed. This way, the main process, as well as other user-defined code, will not be affected by a single malicious user. While this solution will likely work, it seems heavy-handed. Is there no better solution for preventing malicious users from using too much memory?
I'm not particularly set on Javascript, so if there exists any other scripting language that can be run within a JVM and also has support for memory usage limits, I would be open to using it instead of Nashorn. Unfortunately, it seems like Jython, JRuby, and LuaJava all don't have what I'm looking for. Thanks in advance.

Limit resource utilization of JNA calls without changing dll

How can you prevent a JNA method-call from exceeding thresholds for CPU utilization, thread-counts, and memory limits?
Background:
I'm working on a safety critical application and one of the non-safety-critical features requires the use of a library written in C. The dlls have been given to me as a black-box and there's no chance that I'll get access to the source code beyond the java interface files. Is there a way to limit the CPU usage, thread-count, and memory used by the JNA code?
See ulimit and sysctl, which are applicable to your overall JVM process (or any other process, for that matter).
It's not readily possible to segment parts of your JVM which are making native accesses via JNA from those that aren't, though.
You should run some profiling while you exercise your shared library to figure out what resources it does use, so you can focus on setting limits around those (lsof or strace would be used on linux, I'm not sure of the equivalent on windows).
For most operating systems you must either call your C code from a new thread or new process. I would recommend calling it from a new process as then you can sandbox it easier and deeper. Typically on a Unix like system one switches to a new user set aside for the service and that has user resource limits on it. However, on Linux one can use user namespaces and cgroups for more dynamic and flexible sandboxing. On Microsoft Windows one typically uses Job objects for resource sandboxing but permissions based sandboxing is more complicated (a lot of Windows is easily sandboxable with access controls but the GUI and window messaging parts make things complicated and annoying).

Using System.load vs library set as agent

I made a simple library for measuring the size of a given object. The library is
accessed through JNI from a Java class. It's specifically designed for Hotspot, thus it uses the JVMTI and it calls GetObjectSize.
My question is, what's the better solution?
To load the library using System.load("library") or
to set the library as an agent and explicitly load it by issuing the java command with the agent option.
All similar examples I've seen so far employ the agent function:
Determine Java class size from JNI jclass
How to calbulate the size of an object
In what way is that more efficient than just loading the library?
Thanks!
The advantage of command-line injection, is that the agent is loaded together with the Virtual Machine. You can inject the agent into every Java program without modifying the program. With System.load that this done at the point of invocation. You can react to a bigger set of callbacks, for instance there is a VM Initialization Event. If you use System.load that event is bygone.
As a result, I do not believe that using command-line injection is so much more efficient in a cetain way, but rather more effective for some use cases.

Profiling JVMs with JVMTI, how to distinguish the different JVMs?

I am writing a profiler with the aid of the JVM TI.
In C++ I have written a simple agent, which writes the information collected to a socket. With Java Swing I have built a simple GUI which reads these data from a socket to visualize it.
However I am facing some usability issues. I would like to provide the functionality to start profiling a Java application on request. There is the Attach API which provides the possibility to inject an agent into a running JVM.
But to start a new Java program and inject the agent is a little bit more complicated. One way would be, to make a call to the command line and start the Java program from the GUI Profiler:
java -agentlib:agent Program
I kind of dislike this idea, because it is somehow hacky but I see no other way, do you?
To summarize I need two ways to start profiling a JVM:
Start a Java applicatiom from the scratch and start profiling it directly
Attach to a running JVM and inject the agent to start profiling it
Further, I would be in need to distinguish the different JVMs which I inspect, but how to do that? There no unique identifier for the different JVMs. The Attach API gives the possibility to list the different JVMs with their name and id, but what to do in the first case? Is it possible to inject the agent with arguments?
You can also generate your own GUID in the Agent_OnLoad and use that for logging. this way if your some of your processes have short lives and others long lives you can distinguish between recycled PIDS.
I solved the problem by using the local process identification (pid) and the network address to uniquely identfy the JVM.

How to debug JNI heap corruption problems?

I have a Java application that calls lots of different native methods of a legacy application through JNI. But JVM crashes with a stack dump at random places, outside any JNI call. Sometimes it crashes during GC, sometimes during class loading and other places. I suspect that one or more native methods is corrupting JVM heap or some other data structure. I need to know which call is this, so I can fix the native implementation.
The legacy application is a 3rd party DLL for which I don't have sources nor symbol information. To make it callable from Java, I built a wrapper DLL that uses JNI calling conventions.
The perfect solution would be an extended JVM option that forces JVM to automatically check integrity of heap and its other data structures after each JNI call.
Do you know of something that can help?
P.S. Please don't tell me to build a socket or pipe layer between JVM and the legacy application, because our requirements disallow that. This is about bug detection, not architecture design.
Because I went out of answers and couldn't find a ready solution by myself, I ended up building a sandbox process in pure C++ just to identify the problem. My Java app instantiates the sandbox process using ProcessBuilder and then communicates with it using stdin and stdout. Instead of JVM, it's the sandbox who actually loads and calls the legacy DLL. Then I monitored the sandbox process using Microsoft's Application Verifier, which found a memory corruption problem - there was a call passing a buffer smaller than expected. After this was identified, I just increased the length of byte[] used as buffer in the Java app, and now JVM can make direct calls to DLL without use of sandbox.
Overall, I lost almost 10 days just because JVM doesn't have an option to verify heap after each JNI call. But at least now if someone finds a crash we can quickly debug it using the sandbox.

Categories