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.
Related
The only way I know to force garbage collection is to use ForceGarbageCollection() from JVMTI. Is there any cross-platofrm way to force GC (so I don't need to create a JVMTI library for each platform)?
I think that the answer is No.
But I also think that you shouldn't need to do this anyway.
The way to request the garbage collector to run is to call System.gc(). But as the javadoc explains, this can be ignored.
The normal reason that System.gc() is ignored is that the JVM has been launched with the option -XX:+DisableExplicitGC. This is NOT the default. It only happens if the person or script or whatever launching the JVM wants this behavior.
So you are really asking for a way for an application override the user or administrator's explicit instructions to ignore System.gc() calls. You should not be doing that. It is not the application or the application writer's prerogative to override the user's wishes.
If your Java application really needs to run the GC explicitly, include in the installation instructions that it should NOT be run with the -XX:+DisableExplicitGC option. Then System.gc() should work.
So why did they provide a way to disable gc() calls?
Basically because explicitly running the gc() is bad practice (see Why is it bad practice to call System.gc()?) and (nearly always1) unnecessary in a properly written application2. If you application relies on the GC running at specific times to function, then you have made a mistake in the application design.
1 - A couple of exceptions are test cases for code that uses Reference types and similar, and interactive games where you want to (say) clean up between levels to avoid a GC pause during normal play.
2 - It is not uncommon for a Java programmer to start out as a C or C++ programmer. It can be difficult for such people to realize that they don't need to take a hand in Java memory management. The JVM (nearly always) has better understanding of when to run the GC. People also come across Object.finalize and dream up "interesting" ways to use it ... without realizing that it is an expensive and (ultimately) unreliable mechanism.
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,
I'm writing a wrapper in Java for a C++ program. The wrapper is done using SWIG. I have the following problem: when I call a function from Java which create a big object in C++, Java doesn't "see" that it has allocated a lot of memory since it's not allocated in Java's heap. The problem is that the garbage collector is not called when the object is deleted as from Java side there is plenty of free memory. What I have tried is to implement what is described here: http://www.swig.org/Doc1.3/Java.html#java_heap_allocations. The idea is to allocate memory space for C++ in Java's heap. As I'm not interested to use that for every new, I have renamed the new and delete and use them explicitly from my C++ code where needed.
This mechanism seems to work (I can see in that Java's heap is growing and shrinked by the garbage collector) but unfortunately I have a random crash whis seems to occur during a memcpy.
If I invoke the garbage collector manually my program is working but it's not a very clean method.
Thanks for any clue.
In fact I didn't notice the following line in swig website:
If you are going to use optimisations turned on with gcc (for example -O2), ensure you also compile with -fno-strict-aliasing
This seems to have solved the problem
Couldn't you simply manually invoke the C++ object destructor via SWIG? This seems to work for me.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Creating a memory leak with Java
There is a "Garbage Collector" in Java, but does this mean that memory leaks are totally absent in a Java applications? If not, how and why do they happen?
I am more interested in scenarios in applications using JavaSE.
No - memory leaks can still exists in Java. They are just of a "different kind".
Wiki: Memory Leak
A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it [the memory] back to the operating system.
In the case of Java it (normally) is when an unused/unneeded object is never made eligible for reclamation. For instance, an object may be stashed in a global List and never removed even if the object is never accessed later. In this case the JVM won't release the object/memory - it can't - because the object might be needed later, even if it never is.
(As an aside, some objects, such as directly allocated ByteBuffers also consume "out of JVM heap" memory which might not be reclaimed in a timely manner due to the nature of finalizers and memory pressure.)
In the case of Java, a "memory leak" is a semantic issue and not so much an issue of "not being able to release under any circumstances". Of course, with buggy JNI/JNA code, all bets are off ;-)
Happy coding.
Depends on how you define memory leak.
If you specifically mean having allocated memory that is no longer referenced by some memory root, then no, the garbage collector will eventually clean all of those up.
If you mean generally having your memory footprint grow without bound, that is easily possible. Just have some collection referenced by a static field and constantly added to.
Memory leaks in java are very possible. Here is a good article which has an example using core java. Fundamentally, a memory leak happens in java when the garbage collector cannot reclaim an object because the application holds a reference to it that it won't release, even though the object itself might no longer be used. The easiest way to create a memory leak in java is to have your application hold a reference to something, but not using it.
In the example, the unused object is a static List, and adding things to that list will eventually cause the JVM to run out of memory. Static collections are a pretty common source of "leaks", as they are typically long lived and mutable.
There are a few good responses so far. I don't want to recreate those posts, so I'll just add that one thing most people don't think about in connection with this subject is leaks in native code running via JNI. Native code running via JNI uses the JVM's heap space to allocate memory. So, if your application uses native code running via JNI that has a leak, your application has a leak.
Any object that has one or more live references to it will not be garbage-collected. So as long as some variable (either static, in the heap, or in the stack) refers to an object, that object will continue to occupy non-reclaimable memory space.
Unclosed resources (like sockets, JDBC connections, etc.) and constantly growing static collections are some of the better-known leak producers.
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.