Java JNI memory management - java

I want to wrap a C++ library using the Java Native Interface. I wonder how memory management can be done, because afaik Object.finalize() is not garuanteed to be called. I would like to avoid that the user needs to call a free() method. Also, the library would be used in an embeded system, that means some of the objects are owned by the application and some by the Java runtime. When the Java plugin saves a reference to memory that is owned by the application it may happen that the application has already freed it and therefore the reference is invalid.
Was that clear enough?
Thanks,

Related

Does Garbage Collector run in JVM created from C++?

I have a C++ codebase, in which I'm using JNI to create a JVM and occasionally interact with a library implemented in Java. I'm curious whether, in this use case, Java's garbage collector will still reliably run and clean up?
Most of the information that I find online about JNI seems to be about the "opposite" use case, where people generally appear to have mainly Java code, which sometimes interacts with native code through JNI. For such a use case, I find for example the following online:
The automatic garbage collection of local references that are no longer in scope prevents memory leaks in most situations. This automatic garbage collection occurs when a native thread returns to Java (native methods) or detaches from the JVM (Invocation API). Local reference memory leaks are possible if automatic garbage collection does not occur. A memory leak might occur if a native method does not return to the JVM, or if a program that uses the Invocation API does not detach from the JVM.
I'm not sure what exactly "returns to Java" in this context means. Is just occasionally calling into Java-based methods from C++ sufficient, does that already count as "returning to Java"? If not, are there any ways to make sure that the garbage collector gets a chance to run in my use case?
The JVM created with JNI is a full JVM, including GC.
Think of it this way: The java command that you normally use to run Java programs, is nothing but a small JNI program that creates a JVM, locates the class named on the command-line, and makes a static call to the main(String[]) method.

What is a native peer?

Native peer is defined in Effective Java (2nd) as following
A second legitimate use of finalizers concerns objects with native peers. A native peer is a native object to which a normal object delegates via native methods. Because a native peer is not a normal object, the garbage collector doesn’t know about it and can’t reclaim it when its Java peer is reclaimed.
In another question java peer is explained with example. Is it the java class PrintHello or another class which uses PrintHello?
What part is being called a Native Peer here and which part is Java Peer, any example? I understand the use of finalize, I am only confused about which part native peer is being referred to.
A native object is not programmed only in java, but in a platform specific language, typically c or assembler.
Memory allocated by this code cannot be disposed by the GC. Therefore you may need to clean it in a finalizer.
The native peer is the native part of a Java object.
You can see a nice example here:
https://www.javaworld.com/article/2077520/learn-java/java-tip-23--write-native-methods.html
A simple example would be a native window vs. a JFrame. A JFrame is a Java peer, but it needs a (platform dependent) native peer to actually display graphics.
This is why you need to call dispose() when getting rid of a JFrame. You need to get rid of the native component explicitly, because the GC can't touch it.

Monitor jvm heap size from C++

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.

Reliabily unload dll in java

I am trying to unload a dll in java. I have read this and this but it seems that you can not guarantee that the dll will actually be unloaded at a certain time. This is because System.gc() simply "asks kindly" for the garbage collector to run.
So here is a break down of the situation. I have a dll that provides some functionality via JNI. Lets call this dll MainDll. MainDll is loaded from a call to System.load("MainDll"). I need to be able to unload and load this dll on the fly.
Is it possible to create another dll that's sole purpose is to load and unload MainDll. Lets call this dll LoaderDll. I could then simple call System.load("LoaderDll") and have some native functions to load and unload MainDll. The reason for doing this, is I have access to functions on the native system that can load and unload the dll on the fly. The tricky part with this is, will I have still be able to access the native functions I have written in MainDll if it loaded from inside LoaderDll.
Sorry if this is a confusing question. It seems its a little difficult to explain.
Thanks
Create a wrapper DLL that does the loading/unloading. Also have wrapper methods in the DLL that turn around and delegate the calls to the loaded MainDll DLL. This way your Java JNI code only knows about a single DLL. It can still request the unload [LoaderDll::unload()] which internally unloads the MainDll.
This should work as long as the methods/functions in LoaderDll can trigger a load of MainDll when they are called when MainDll is not currently loaded, assuming that is the desired behavior instead of throwing an exception/error.
One issue with this would be that LoaderDll would always be loaded.
Add a level of indirection.
Make your native methods call forwarding routines in LoaderDLL. The forwarding routines can use C facilities to forward the calls to code in mainDLL.
If you have a need to dynamically load and unload code, have you considered OSGi. This works in felix at least.
In Oracle/Sun's JDK, System.gc() will trigger a full gc (unless it has been turned off on the command line). It could be just a hint on other JVMs.
Based on your clarifying comments, I think the simplest approach would be to spawn a new JVM, whose sole responsibility is managing your DLL. Probably exposing an RMI interface to access those classes (although a simple stream may be sufficient).
I haven't still encountered a situation where System.gc() not to trigger the garbage collector although it is just a hint.
This tutorial actually helped me to do my work: Unload Java JNI DLL

Java memory Management for JNI

I have two questions :
What if I have a JNI call to a method and the JNI method leaks memory. Once this method completes will the JVM Garbage collector be able to get that memory back. I heard that the JVM does not manage the Heap Space used by JNI ? But the memory used by JNI is a part of the memory used by the Java process ?
Is it absolutely necessary to use JNI to achieve IPC ? What are the other popular Java techniques or is there a Open Source Library to achieve Shared memory in Java ?
No: "the JNI framework does not provide any automatic garbage collection for non-JVM memory resources allocated by code executing on the native side" (Wikipedia).
No, Java has sockets and indeed ProcessBuilder. Shared memory can be achieved with MappedByteBuffer.
You need deallocate any os resource created in native code, such as File Descriptor, memory address (allocate by malloc. etc) because they are not binding with any jvm instance.
You can consider use Memory-Mapped Files (sample).
You can use RPCs (between computer and computer) in IPC context, such as socket, web service, JMS, etc.
in all likelihood yes - though i'm not entirely sure whether there doesn't exist a way to clear that memory.
take a look at ProcessBuilder - it might be of some help to exclude JNI to achieve IPC.

Categories