RAM does not clear even after calling System.gc() - java

This is a sample code of my main application problem. When I generate the data it continues to take the RAM (by the way its OK). But when I stop the process it still remain in the RAM (I can see it in the Task Manager). I tried to use the System.gc() but it also didn't work. At some point the program got stuck, because of it taking up more memory. Hope somebody can help me.
public static ArrayList<String> my = new ArrayList<>();
public static int val = 0;
// Code for Start Button
try {
new Thread(new Runnable() {
#Override
public void run() {
String ss = "";
for (int i = 0; i < 10000; i++) {
ss += "ABC";
}
while (true) {
if (val == 0) {
for (int i = 0; i < 30; i++) {
my.add(ss + new SimpleDateFormat("yyyyMMddHHmmssSSS"));
}
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
}
} else {
Thread.yield();
break;
}
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
// Code for Stop Button
val = 1;
my.clear();
my = null;
System.gc();
Runtime.getRuntime().freeMemory();

Garbage collection depends on the various factor like which collector you're using, machine's physical memory as well as the JVM version you are using. Since you're not mentioned so much here about them, bit hard to predict which could be the cause for this. I assume you're using Java 8 since that's the more popular version nowadays.
Since Java 8, There's a change in JVM memory model. Which is, now there is no Permanent Generation space. This's the space where String Pool located (I'm going with String hence you're using a String concatenation in loops). Refer this Java (JVM) Memory Model – Memory Management in Java document. Permanent Generation is where the class/static references live since you declare them as well.
Instead of Permanent Generation, Since Java 8, there's a new memory location called Metaspace which lives in the Main memory outside of JVM.
Also, when you concatenate String objects like this, it won't modify the existing object as String is immutable type. Instead, it creates new String objects with the new value and put them into the Metaspace. This might be the reason you're seeing a memory usage increment.
Even though Metaspace is located inside the main memory/physical memory and it can dynamically expand, still has the physical memory limitation. That's why I told earlier machine's physical memory as a dependency factor.
When we come to garbage collection, you haven't mention any GC config. So I assume you are using Parallel GC which is the default collector of Java 8 (You can find more about the GCs from same link provided above). I guess the Parallel GC's performance is adequate for this task. Therefore invoking System.gc() whould be enough without any JVM flag.
But, as you mentioned that System.gc() doesn't clean up the memory could occurs hence you're using a separate thread to concatenate these Strings.
Usually, Strings that created using String literal (String s = "abc") would not become garbage eligible. This because there is a implicit reference to the String object in the code of every method that uses the literal (Check this answer When will a string be garbage collected in java). Thus, you have to loose those implicit references by ending the execution of the function.
Since you're using a new Thread to do this concatenation and I can't find any place where you interrupt the thread and you're invoking the Thread.yield()(Thread.yield) to inform the thread scheduler to seize the usage of the CPU for this particular thread and mark the thread is willing to be scheduled as soon as possible again, make pretty much clear this Thread object still lives and refers those String objects not making them garbage eligible. This maybe the reason System.gc() invocation is not working.
As a solution, try to interrupt the thread instead of yield.
Update 1:
Before Java 7, String Pool was located in PermGen, which is not eligible for garbage collection. PermGen has a fixed size and not capable to expand at runtime. If PermGen has not enough space, it gives java.lang.OutOfMemoryError: PermGen error. As a temporary remediation we can increase the PermGen size using -XX:MaxPermSize=512m flag.
But remember this is only works on JVMs before Java 8 and in Java 7, this doesn't make any different in the sense of increasing String Pool size availability hence Java 7 onwards, String Pool has moved to Heap space.

Related

Is it possible to stop the garbage collector OR to force it to run at specific time? [duplicate]

Is it possible to force garbage collection in Java, even if it is tricky to do? I know about System.gc(); and Runtime.gc(); but they only suggest to do GC. How can I force GC?
Your best option is to call System.gc() which simply is a hint to the garbage collector that you want it to do a collection. There is no way to force and immediate collection though as the garbage collector is non-deterministic.
The jlibs library has a good utility class for garbage collection. You can force garbage collection using a nifty little trick with WeakReference objects.
RuntimeUtil.gc() from the jlibs:
/**
* This method guarantees that garbage collection is
* done unlike <code>{#link System#gc()}</code>
*/
public static void gc() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
System.gc();
}
}
The best (if not only) way to force a GC would be to write a custom JVM. I believe the Garbage collectors are pluggable so you could probably just pick one of the available implementations and tweak it.
Note: This is NOT an easy answer.
Using the Java™ Virtual Machine Tool Interface (JVM TI), the function
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
will "Force the VM to perform a garbage collection." The JVM TI is part of the JavaTM Platform Debugger Architecture (JPDA).
YES it is almost possible to forced you have to call to methods in the same order and at the same time this ones are:
System.gc ();
System.runFinalization ();
even if is just one object to clean the use of this two methods at the same time force the garbage collector to use the finalise() method of unreachable object freeing the memory assigned and doing what the finalize() method states.
HOWEVER it is a terrible practice to use the garbage collector because the use of it could introduce an over load to the software that may be even worst than on the memory, the garbage collector has his own thread which is not possible to control plus depending on the algorithm used by the gc could take more time and is consider very inefficient, you should check your software if it worst with the help of the gc because it is definitely broke, a good solution must not depend on the gc.
NOTE: just to keep on mind this will works only if in the finalize method is not a reassignment of the object, if this happens the object will keep alive an it will have a resurrection which is technically possible.
Under the documentation for OutOfMemoryError it declares that it will not be thrown unless the VM has failed to reclaim memory following a full garbage collection. So if you keep allocating memory until you get the error, you will have already forced a full garbage collection.
Presumably the question you really wanted to ask was "how can I reclaim the memory I think I should be reclaiming by garbage collection?"
You can trigger a GC from the command line. This is useful for batch/crontab:
jdk1.7.0/bin/jcmd <pid> GC.run
See :
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html
To manually Request GC (not from System.gc()) :
Go To : bin folder in JDK eg.-C:\Program Files\Java\jdk1.6.0_31\bin
Open jconsole.exe
Connect to the desired local Process.
Go To memory tab and click perform GC.
How to Force Java GC
Okay, here are a few different ways to force Java GC.
Click JConsole's Perform GC button
Use JMap's jmap -histo:live 7544 command where 7544 is the pid
Call the Java Diagnostic Console's jcmd 7544 GC.run command
Call System.gc(); in your code
Call Runtime.getRuntime().gc(); in your code
None of these work
Here's the dirty little secret. None of these are guaranteed to work. You really can't force Java GC.
The Java garbage collection algos are non-deterministic, and while all of these methods can motivate the JVM to do GC, you can't actually force it. If the JVM has too much going on and a stop-the-world operation is not possible, these commands will either error out, or they will run but GC won't actually happen.
if (input.equalsIgnoreCase("gc")) {
System.gc();
result = "Just some GC.";
}
if (input.equalsIgnoreCase("runtime")) {
Runtime.getRuntime().gc();
result = "Just some more GC.";
}
Fix the darn problem
If you've got a memory leak or object allocation problem, then fix it. Sitting around with your finger on Java Mission Control's Force Java GC button only kicks the can down the road. Profile your app with Java Flight Recorder, view the results in VisualVM or JMC, and fix the problem. Trying to force Java GC is a fools game.
.gc is a candidate for elimination in future releases - a Sun Engineer once commented that maybe fewer than twenty people in the world actually know how to use .gc() - I did some work last night for a few hours on a central / critical data-structure using SecureRandom generated data, at somewhere just past 40,000 objects the vm would slow down as though it had run out of pointers. Clearly it was choking down on 16-bit pointer tables and exhibited classic "failing machinery" behavior.
I tried -Xms and so on, kept bit twiddling until it would run to about 57,xxx something. Then it would run gc going from say 57,127 to 57,128 after a gc() - at about the pace of code-bloat at camp Easy Money.
Your design needs fundamental re-work, probably a sliding window approach.
JVM specification doesn't say anything specific about garbage collection. Due to this, vendors are free to implement GC in their way.
So this vagueness causes uncertainty in garbage collection behavior. You should check your JVM details to know about the garbage collection approaches/algorithms. Also there are options to customize behavior as well.
If you need to force garbage collection, perhaps you should consider how you're managing resources. Are you creating large objects that persist in memory? Are you creating large objects (e.g., graphics classes) that have a Disposable interface and not calling dispose() when done with it? Are you declaring something at a class level that you only need within a single method?
It would be better if you would describe the reason why you need garbage collection. If you are using SWT, you can dispose resources such as Image and Font to free memory. For instance:
Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();
There are also tools to determine undisposed resources.
Another options is to not create new objects.
Object pooling is away to reduce the need GC in Java.
Object pooling is generally not going to be faster than Object creation (esp for lightweight objects) but it is faster than Garbage Collection. If you created 10,000 objects and each object was 16 bytes. That's 160,000 bytes GC has to reclaim. On the other hand, if you don't need all 10,000 at the same time, you can create a pool to recycle/reuse the objects which eliminates the need to construct new objects and eliminates the need to GC old objects.
Something like this (untested).
And if you want it to be thread safe you can swap out the LinkedList for a ConcurrentLinkedQueue.
public abstract class Pool<T> {
private int mApproximateSize;
private LinkedList<T> mPool = new LinkedList<>();
public Pool(int approximateSize) {
mApproximateSize = approximateSize;
}
public T attain() {
T item = mPool.poll();
if (item == null) {
item = newInstance();
}
return item;
}
public void release(T item) {
int approxSize = mPool.size(); // not guaranteed accurate
if (approxSize < mApproximateSize) {
recycle(item);
mPool.add(item);
} else if (approxSize > mApproximateSize) {
decommission(mPool.poll());
}
}
public abstract T newInstance();
public abstract void recycle(T item);
public void decommission(T item) { }
}
You can try using Runtime.getRuntime().gc() or use utility method System.gc() Note: These methods do not ensure GC. And their scope should be limited to JVM rather than programmatically handling it in your application.
We can trigger jmap -histo:live <pid> using the java runtime. This will force a full GC on heap to mark all the live objects.
public static void triggerFullGC() throws IOException, InterruptedException {
String pid = ManagementFactory.getRuntimeMXBean().getName().split("#")[0];
Process process = Runtime.getRuntime().exec(
String.format("jmap -histo:live %s", pid)
);
System.out.println("Process completed with exit code :" + process.waitFor());
}
I did some experimentation (see https://github.com/mikenakis/ForcingTheJvmToGarbageCollect) trying about a dozen different ways of performing a garbage collection, including ways described in this answer, and more, and I found that there is absolutely no frigging way to deterministically force the JVM to do a complete garbage collection. Even the best answers to this question are only partially successful in that the best they achieve is some garbage collection, but never a guaranteed full garbage collection.
My experimentation has showed that the following code snippet yields the best (least bad) results:
public static void ForceGarbageCollection()
{
long freeMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
for( ; ; )
{
Runtime.getRuntime().gc();
Runtime.getRuntime().runFinalization();
long newFreeMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
if( newFreeMemory == freeMemory )
break;
freeMemory = newFreeMemory;
sleep( 10 );
}
}
Where the sleep() function is as follows:
private static void sleep( int milliseconds )
{
try
{
Thread.sleep( milliseconds );
}
catch( InterruptedException e )
{
throw new RuntimeException( e );
}
}
Unfortunately, that number 10 in that sleep( 10 ) is magic; it assumes that you are doing a moderate number of memory allocations per second, which incur a moderate amount of finalization. If you are going through objects faster, then 10 might be inadequate and you may need to wait longer. You could set it to 100 to be sure, but no matter what you set it to, there will always be a chance that it will not be enough.
That having been said, in a controlled environment where that 10 is enough, this approach has been observed to consistently eliminate all unreachable objects from memory, while no other approach mentioned in this Q&A does. The experiment code I linked to on github proves so.
In my opinion, the fact that the Java Virtual Machine provides no means of performing a forced-on-demand, unconditional, deterministic, absolutely thorough, stop-the-world garbage collection makes it BROKEN.
To put it in a different way, the creators of the JVM are so full of hubris as to think that they know better than us whether we want to do that or whether we should want to do that. Don't be so arrogant. If something works as if by magic, then some means of bypassing the magic must be provided.
I wanted to force gc, because my code was frozen for a long time when it happened. The aim is to smooth the charge, by regularly cause gc.
The solutions listed doesnt forced anything in my environment.
So:
I request the memory for temporary variable,
simply, by increments,
and monitor the memory and stop the operation as soon as gc is triggered.
It works easily but you have to tune.
Runtime rt = Runtime.getRuntime();
double usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
if (usedMB > 1000) // only when necessary
{
byte[][] for_nothing = new byte[10][];
for (int k = 0; k < 10 ; k ++)
for_nothing[k] = new byte[100_000_000];
}
System.gc();
Runtime.getRuntime().gc();
Runtime.getRuntime().runFinalization();
If you are running out of memory and getting an OutOfMemoryException you can try increasing the amount of heap space available to java by starting you program with java -Xms128m -Xmx512m instead of just java. This will give you an initial heap size of 128Mb and a maximum of 512Mb, which is far more than the standard 32Mb/128Mb.
Really, I don't get you. But to be
clear about "Infinite Object Creation"
I meant that there is some piece of
code at my big system do creation of
objects whom handles and alive in
memory, I could not get this piece of
code actually, just gesture!!
This is correct, only gesture. You have pretty much the standard answers already given by several posters. Let's take this one by one:
I could not get this piece of code
actually
Correct, there is no actual jvm - such is only a specification, a bunch of computer science describing a desired behaviour ... I recently dug into initializing Java objects from native code. To get what you want, the only way is to do what is called aggressive nulling. The mistakes if done wrong are so bad doing that we have to limit ourselves to the original scope of the question:
some piece of code at my big system
do creation of objects
Most of the posters here will assume you are saying you are working to an interface, if such we would have to see if you are being handed the entire object or one item at a time.
If you no longer need an object, you can assign null to the object but if you get it wrong there is a null pointer exception generated. I bet you can achieve better work if you use NIO
Any time you or I or anyone else gets: "Please I need that horribly." it is almost universal precursor to near total destruction of what you are trying to work on .... write us a small sample code, sanitizing from it any actual code used and show us your question.
Do not get frustrated. Often what this resolves to is your dba is using a package bought somewhere and the original design is not tweaked for massive data structures.
That is very common.
FYI
The method call System.runFinalizersOnExit(true) guarantees that finalizer methods
are called before Java shuts down. However, this method is inherently unsafe
and has been deprecated. An alternative is to add “shutdown hooks” with the method
Runtime.addShutdownHook.
Masarrat Siddiqui
There is some indirect way for forcing garbage collector. You just need to fill heap with temporary objects until the point when garbage collector will execute. I've made class which forces garbage collector in this way:
class GarbageCollectorManager {
private static boolean collectionWasForced;
private static int refCounter = 0;
public GarbageCollectorManager() {
refCounter++;
}
#Override
protected void finalize() {
try {
collectionWasForced = true;
refCounter--;
super.finalize();
} catch (Throwable ex) {
Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int forceGarbageCollection() {
final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
int iterationsUntilCollected = 0;
collectionWasForced = false;
if (refCounter < 2)
new GarbageCollectorManager();
while (!collectionWasForced) {
iterationsUntilCollected++;
int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
arr = null;
}
return iterationsUntilCollected;
}
}
Usage:
GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();
I don't know how much this method is useful, because it fills heap constantly, but if you have mission critical application which MUST force GC - when this may be the Java portable way to force GC.
I would like to add some thing here. Please not that Java runs on Virtual Machine and not actual Machine. The virtual machine has its own way of communication with the machine. It may varry from system to system. Now When we call the GC we ask the Virtual Machine of Java to call the Garbage Collector.
Since the Garbage Collector is with Virtual Machine , we can not force it to do a cleanup there and then. Rather that we queue our request with the Garbage Collector. It depends on the Virtual Machine, after particular time (this may change from system to system, generally when the threshold memory allocated to the JVM is full) the actual machine will free up the space. :D
On OracleJDK 10 with G1 GC, a single call to System.gc() will cause GC to clean up the Old Collection. I am not sure if GC runs immediately. However, GC will not clean up the Young Collection even if System.gc() is called many times in a loop. To get GC to clean up the Young Collection, you must allocate in a loop (e.g. new byte[1024]) without calling System.gc(). Calling System.gc() for some reason prevents GC from cleaning up the Young Collection.
If you are using JUnit and Spring, try adding this in every test class:
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

Avoiding PermGen out of memory and GC overhead limit exceeded

I'm trying to generate classes and load them at run time.
I'm using a ClassLoader object to load the classes. Since I don't want to run out of PermGen memory, from time to time I un-reference the class loader and create a new one to load the new classes to be used. This seems to work fine and I don't get a PermGen out of memory.
The problem is that when I do that, after a while I get the following error:
java.lang.OutOfMemoryError: GC overhead limit exceeded
So my question is, when should I un-reference the class loader to avoid both errors?: Should I monitor in my code the PermGen usage so that I un-reference the class loader and call System.gc() when the PermGen usage is close to the limit?
Or should I follow a different approach? Thanks
There is no single correct answer to this.
On the one hand, if unlinking the classloader is solving your permgen leakage problems, then you should continue to do that.
On the other hand, a "GC overhead limit exceeded" error means that your application is spending too much time garbage collection. In most circumstances, this means that your heap is too full. But that can mean one of two things:
The heap is too small for your application's requirements.
Your application has a memory leak.
You could assume that the problem is the former one and just increase the heap size. But if the real problem is the latter one, then increasing the heap size is just postponing the inevitable ... and the correct thing to do would be to find and fix the memory leak.
Don't call System.gc(). It won't help.
Are you loading the same class multiple times?
Because you should cache the loaded class.
If not, how many classes are you loading?
If they are plenty you may have to fix a limit of loaded classes (this number can be either based on heap size or a number based on how much memory does it take to have a loaded class) and discard the least used when loading the next one.
I had somewhat similar situation with class unloading.
I'm using several class loaders to simulate multiple JVM inside of JUnit test (this is usually used to work with Oracle Coherence cluster, but I was also successfully used this technique to start multi node HBase/Hadoop cluster inside of JVM).
For various reasons tests may require restart of such "virtual" JVM, which means forfeiting old ClassLoader and creating new one.
Sometimes JVM delays class unloading event if you for Full GC, which leads to various problems later.
One technique I found usefully for forcing JVM to collect PermSpace is following.
public static void forcePermSpaceGC(double factor) {
if (PERM_SPACE_MBEAN == null) {
// probably not a HotSpot JVM
return;
}
else {
double f = ((double)getPermSpaceUsage()) / getPermSpaceLimit();
if (f > factor) {
List<String> bloat = new ArrayList<String>();
int spree = 0;
int n = 0;
while(spree < 5) {
try {
byte[] b = new byte[1 << 20];
Arrays.fill(b, (byte)('A' + ++n));
bloat.add(new String(b).intern());
spree = 0;
}
catch(OutOfMemoryError e) {
++spree;
System.gc();
}
}
return;
}
}
}
Full sourcecode
I'm filling PermSpace with String using intern() until JVM would collect them.
But
I'm using that technique for testing
Various combination of hardware / JVM version may require different threshold, so it is often quicker to restart whole JVM instead of forcing it to properly collect all garbage

Understanding Java Memory Management

Java programmers know that JVM runs a Garbage Collector, and System.gc() would just be a suggestion to JVM to run a Garbage Collector. It is not necessarily that if we use System.gc(), it would immediately run the GC.Please correct me if I misunderstand Java's Garbage Collector.
Is/are there any other way/s doing memory management other than relying on Java's Garbage Collector?If you intend to answer the question by some sort of programming practice that would help managing the memory, please do so.
The most important thing to remember about Java memory management is "nullify" your reference.
Only objects that are not referenced are to be garbage collected.
For example, objects in the following code is never get collected and your memory will be full just to do nothing.
List objs = new ArrayList();
for (int i = 0; i < Integer.MAX_VALUE; i++) objs.add(new Object());
But if you don't reference those object ... you can loop as much as you like without memory problem.
List objs = new ArrayList();
for (int i = 0; i < Integer.MAX_VALUE; i++) new Object();
So what ever you do, make sure you remove reference to object to no longer used (set reference to null or clear collection).
When the garbage collector will run is best left to JVM to decide. Well unless your program is about to start doing things that use a lot of memory and is speed critical so you may suggest JVM to run GC before going in as you may likely get the garbaged collected and extra memory to go on. Other wise, I personally see no reason to run System.gc().
Hope this helps.
Below is little summary I wrote back in the days (I stole it from some blog, but I can't remember where from - so no reference, sorry)
There is no manual way of doing garbage collection in Java.
Java Heap is divided into three generation for the sake of garbage collection. These are the young generation, tenured or old generation, and Perm area.
New objects are created in the young generation and subsequently moved to the old generation.
String pool is created in Perm area of Heap, Garbage collection can occur in perm space but depends on upon JVM to JVM.
Minor garbage collection is used to move an object from Eden space to Survivor 1 and Survivor 2 space, and Major collection is used to move an object from young to tenured generation.
Whenever Major garbage collection occurs application, threads stops during that period which will reduce application’s performance and throughput.
There are few performance improvements has been applied in garbage collection in Java 6 and we usually use JRE 1.6.20 for running our application.
JVM command line options -Xms and -Xmx is used to setup starting and max size for Java Heap. The ideal ratio of this parameter is either 1:1 or 1:1.5 based on my experience, for example, you can have either both –Xmx and –Xms as 1GB or –Xms 1.2 GB and 1.8 GB.
Command line options: -Xms:<min size> -Xmx:<max size>
Just to add to the discussion: Garbage Collection is not the only form of Memory Management in Java.
In the past, there have been efforts to avoid the GC in Java when implementing the memory management (see Real-time Specification for Java (RTSJ)). These efforts were mainly dedicated to real-time and embedded programming in Java for which GC was not suitable - due to performance overhead or GC-introduced latency.
The RTSJ characteristics
Immortal and Scoped Memory Management - see below for examples.
GC and Immortal/Scoped Memory can coexist withing one application
RTSJ requires a specially modified JVM.
RTSJ advantages:
low latency, no GC pauses
delivers predictable performance that is able to meet real-time system requirements
Why RTSJ failed/Did not make a big impact:
Scoped Memory concept is hard to program with, error-prone and difficult to learn.
Advance in Real-time GC algoritms reduced the GC pause-time in such way that Real-time GCs replaced the RTSJ in most of the real-time apps. However, Scoped Memories are still used in places where no latencies are tolerated.
Scoped Memory Code Example (take from An Example of Scoped Memory Usage):
import javax.realtime.*;
public class ScopedMemoryExample{
private LTMemory myMem;
public ScopedMemoryExample(int Size) {
// initialize memory
myMem = new LTMemory(1000, 5000);
}
public void periodicTask() {
while (true)) {
myMem.enter(new Runnable() {
public void run() {
// do some work in the SCOPED MEMORY
new Object();
...
// end of the enter() method, the scoped Memory is emptied.
}
});
}
}
}
Here, a ScopedMemory implementation called LTMemory is preallocated. Then a thread enters the scoped memory, allocates the temporary data that are needed only during the time of the computation. After the end of the computation, the thread leaves the scoped memory which immediately makes the whole content of the specific ScopedMemory to be emptied. No latency introduced, done in constant time e.g. predictable time, no GC is triggered.
From my experience, in java you should rely on the memory management that is provided by JVM itself.
The point I'd focus on in this topic is to configure it in a way acceptable for your use case. Maybe checking/understanding JVM tuning options would be useful: http://docs.oracle.com/cd/E15523_01/web.1111/e13814/jvm_tuning.htm
You cannot avoid garbage collection if you use Java. Maybe there are some obscure JVM implementations that do, but I don't know of any.
A properly tuned JVM shouldn't require any System.gc() hints to operate smoothly. The exact tuning you would need depends heavily on what your application does, but in my experience, I always turn on the concurrent-mark-and-sweep option with the following flag: -XX:+UseConcMarkSweepGC. This flag allows the JVM to take advantage of the extra cores in your CPU to clean up dead memory on a background thread. It helps to drastically reduce the amount of time your program is forcefully paused when doing garbage collections.
Well, the GC is always there -- you can't create objects that are outside its grasp (unless you use native calls or allocate a direct byte buffer, but in the latter case you don't really have an object, just a bunch of bytes). That said, it's definitely possible to circumvent the GC by reusing objects. For instance, if you need a bunch of ArrayList objects, you could just create each one as you need it and let the GC handle memory management; or you could call list.clear() on each one after you finish with it, and put it onto some queue where somebody else can use it.
Standard best practices are to not do that sort of reuse unless you have good reason to (ie, you've profiled and seen that the allocations + GC are a problem, and that reusing objects fixes that problem). It leads to more complicated code, and if you get it wrong it can actually make the GC's job harder (because of how the GC tracks objects).
Basically the idea in Java is that you should not deal with memory except using "new" to allocate new objects and ensure that there is no references left to objects when you are done with them.
All the rest is deliberately left to the Java Runtime and is - also deliberately - defined as vaguely as possible to allow the JVM designers the most freedom in doing so efficiently.
To use an analogy: Your operating system manages named areas of harddisk space (called "files") for you. Including deleting and reusing areas you do not want to use any more. You do not circumvent that mechanism but leave it to the operating system
You should focus on writing clear, simple code and ensure that your objects are properly done with. This will give the JVM the best possible working conditions.
You are correct in saying that System.gc() is a request to the compiler and not a command. But using below program you can make sure it happens.
import java.lang.ref.WeakReference;
public class GCRun {
public static void main(String[] args) {
String str = new String("TEMP");
WeakReference<String> wr = new WeakReference<String>(str);
str = null;
String temp = wr.get();
System.out.println("temp -- " + temp);
while(wr.get() != null) {
System.gc();
}
}
}
I would suggest to take a look at the following tutorials and its contents
This is a four part tutorial series to know about the basics of garbage collection in Java:
Java Garbage Collection Introduction
How Java Garbage Collection Works?
Types of Java Garbage Collectors
Monitoring and Analyzing Java Garbage Collection
I found This tutorial very helpful.
"Nullify"ing the reference when not required is the best way to make an object eligible for Garbage collection.
There are 4 ways in which an object can be Garbage collected.
Point the reference to null, once it is no longer required.
String s = new String("Java");
Once this String is not required, you can point it to null.
s = null;
Hence, s will be eligible for Garbage collection.
Point one object to another, so that both reference points to same object and one of the object is eligible for GC.
String s1 = new String("Java");
String s2 = new String("C++");
In future if s2 also needs to pointed to s1 then;
s1 = s2;
Then the object having "Java" will be eligible for GC.
All the objects created within a method are eligible for GC once the method is completed. Hence, once the method is destroyed from the stack of the thread then the corresponding objects in that method will be destroyed.
Island of Isolation is another concept where the objects with internal links and no extrinsic link to reference is eligible for Garbage collection.
"Island of isolation" of Garbage Collection
Examples:
Below is a method of Camera class in android. See how the developer has pointed mCameraSource to null once it is not required. This is expert level code.
public void release() {
if (mCameraSource != null) {
mCameraSource.release();
mCameraSource = null;
}
}
How Garbage Collector works?
Garbage collection is performed by the daemon thread called Garbage Collector. When there is sufficient memory available that time this demon thread has low priority and it runs in background. But when JVM finds that the heap is full and JVM wants to reclaim some memory then it increases the priority of Garbage collector thread and calls Runtime.getRuntime.gc() method which searches for all the objects which are not having reference or null reference and destroys those objects.

Easiest way to cause a memory leak in Java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Creating a memory leak with Java
What's the easiest way to cause a Java memory leak?
You cannot really "leak memory" in Java unless you:
intern strings
generate classes
leak memory in the native code called by JNI
keep references to things that you do not want in some forgotten or obscure place.
I take it that you are interested in the last case. The common scenarios are:
listeners, especially done with inner classes
caches.
A nice example would be to:
build a Swing GUI that launches a potentially unlimited number of modal windows;
have the modal window do something like this during its initialization:
StaticGuiHelper.getMainApplicationFrame().getOneOfTheButtons().addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
// do nothing...
}
})
The registered action does nothing, but it will cause the modal window to linger in memory forever, even after closing, causing a leak - since the listeners are never unregistered, and each anonymous inner class object holds a reference (invisible) to its outer object. What's more - any object referenced from the modal windows have a chance of leaking too.
This is why libraries such as EventBus use weak references by default.
Apart from listeners, other typical examples are caches, but I cannot think of a nice example.
First we have to agree on what a memory leak actually is.
Wikipedia used to describe a memory leak like this:
A memory leak, in computer science (or leakage, in this context), occurs when a computer program consumes memory but is unable to release it back to the operating system.
However this has changed multiple times and right now (02/2023) it says:
In computer science, a memory leak is a type of resource leak that occurs when a computer program incorrectly manages memory allocations in a way that memory which is no longer needed is not released.
Depending on the context you need to specify what exactly you are looking for more precisely.
Unreachable dynamically allocated memory
First, let us have a quick look at an example from a language without automatic memory management: In C you can use malloc() in order to allocate some memory. This function returns a pointer to the allocated memory. You must call free() on exactly this pointer in order to release the memory back to the operating system. But what if the pointer is used in multiple places? Who is responsible for calling free()? If you release the memory too early, then some parts of your application that is still working with that memory is broken. If you do not release the memory, you have a leak. If all pointers to the memory allocated are lost (overwritten or lifetime exceeded), then your application will be unable to release the memory back to the operating system. This would fulfill the old definition that Wikipedia had for a memory leak in 2011. To avoid this, you need some kind of contract that defines who is responsible for freeing memory that was allocated. This requires documentation, which must be read, correctly understood and followed by possibly many people creating various opportunities for errors.
Automatic memory management (which Java has) frees you from this danger. In Java you can allocate memory using the keyword new, but there is no free in Java. new returns a "reference", which (in this context) behaves similarly to a pointer. When all references to allocated memory are lost (overwritten or lifetime exceeded) then this is detected automatically and the memory is returned to the operating system.
In Java this type of memory leak is only "available" in case of bugs in the garbage collector, JNI modules that leak memory or similar, but at least in theory you are safe.
Other programming errors
That withstanding it is of course both with and without automatic memory management possible to actively maintain unneeded references. Assume the following class:
class Demo {
private static final LinkedList<Integer> history = new LinkedList<>(Collections.singleton(0));
public static int plusPrevious(int value) {
int result = history.getLast() + value;
history.add(value);
return result;
}
}
Everytime someone calls plusPrevious the history-List grows. But why? Only one value is needed, not the full history. This class is holding on to memory which it does not need. This fulfills the current definition that Wikipedia has for a memory leak.
In this case the error is obvious. However in more complicated scenarios it might not be so easy to decide what is still "needed" and what is not.
At any rate, putting things in static variables is "good" start to get into trouble. If in the example above the history were not static then a user of that class might eventually release the reference to the instance of Demo and thus free the memory. However since it is static the history will hang around until the application as a whole terminates.
Here's a simple example
public class Finalizer {
#Override
protected void finalize() throws Throwable {
while (true) {
Thread.yield();
}
}
public static void main(String[] args) {
while (true) {
for (int i = 0; i < 100000; i++) {
Finalizer f = new Finalizer();
}
System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
}
}
}
Use:
public static List<byte[]> list = new ArrayList<byte[]>();
And then add (big) arrays without removing them. At some point you will run out of memory without suspecting it. (You can do this with any objects, but with big, full arrays you can run out of memory faster.)
In Java, if you dereference an object (it falls out of scope), it is garbage collected. So you have to hold a reference to it in order to have a memory problem.
Create a collection of objects at class scope
Periodically add new objects to the collection
Do not drop the reference to the instance of the class that holds the collection
Because there is always a reference to the collection and the instance of the object that owns the collection, the garbage collector will never clean up that memory, thus causing a "leak" over time.
From what I've read in the most voted answer, you are most probably asking for a C-like memory leak. Well, since there's garbage collection, you can't allocate an object, lose all its references and get it still occupying memory - that would be a serious JVM bug.
On the other hand, you can happen to leak threads - which, of course, would cause this state, because you would have some thread running with its references to objects, and you may lose the thread's reference. You can still get the Thread reference through the API - see http://www.exampledepot.com/egs/java.lang/ListThreads.html
The following extremely contrived Box class will leak memory if used. Objects that are put into this class are eventually (after another call to put to be precise... provided the same object is not re-put into it.) inaccessible to the outside world. They cannot be dereferenced through this class, yet this class ensures they cannot be collected. This is a real leak. I know this is really contrived, but similar cases are possible to do by accident.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Stack;
public class Box <E> {
private final Collection<Box<?>> createdBoxes = new ArrayList<Box<?>>();
private final Stack<E> stack = new Stack<E>();
public Box () {
createdBoxes.add(this);
}
public void put (E e) {
stack.push(e);
}
public E get () {
if (stack.isEmpty()) {
return null;
}
return stack.peek();
}
}
Try this simple class:
public class Memory {
private Map<String, List<Object>> dontGarbageMe = new HashMap<String, List<Object>>();
public Memory() {
dontGarbageMe.put("map", new ArrayList<Object>());
}
public void useMemInMB(long size) {
System.out.println("Before=" + getFreeMemInMB() + " MB");
long before = getFreeMemInMB();
while ((before - getFreeMemInMB()) < size) {
dontGarbageMe.get("map").add("aaaaaaaaaaaaaaaaaaaaaa");
}
dontGarbageMe.put("map", null);
System.out.println("After=" + getFreeMemInMB() + " MB");
}
private long getFreeMemInMB() {
return Runtime.getRuntime().freeMemory() / (1024 * 1024);
}
public static void main(String[] args) {
Memory m = new Memory();
m.useMemInMB(15); // put here apropriate huge value
}
}
It does seem that most of the answers are not C style memory leaks.
I thought I'd add an example of a library class with a bug that will give you an out-of-memory exception. Again, it is not a true memory leak, but it is an example of something running out of memory that you would not expect.
public class Scratch {
public static void main(String[] args) throws Exception {
long lastOut = System.currentTimeMillis();
File file = new File("deleteme.txt");
ObjectOutputStream out;
try {
out = new ObjectOutputStream(
new FileOutputStream("deleteme.txt"));
while (true) {
out.writeUnshared(new LittleObject());
if ((System.currentTimeMillis() - lastOut) > 2000) {
lastOut = System.currentTimeMillis();
System.out.println("Size " + file.length());
// out.reset();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class LittleObject implements Serializable {
int x = 0;
}
You will find the original code and bug description at JDK-4363937: ObjectOutputStream is creating a memory leak

How to force garbage collection in Java?

Is it possible to force garbage collection in Java, even if it is tricky to do? I know about System.gc(); and Runtime.gc(); but they only suggest to do GC. How can I force GC?
Your best option is to call System.gc() which simply is a hint to the garbage collector that you want it to do a collection. There is no way to force and immediate collection though as the garbage collector is non-deterministic.
The jlibs library has a good utility class for garbage collection. You can force garbage collection using a nifty little trick with WeakReference objects.
RuntimeUtil.gc() from the jlibs:
/**
* This method guarantees that garbage collection is
* done unlike <code>{#link System#gc()}</code>
*/
public static void gc() {
Object obj = new Object();
WeakReference ref = new WeakReference<Object>(obj);
obj = null;
while(ref.get() != null) {
System.gc();
}
}
The best (if not only) way to force a GC would be to write a custom JVM. I believe the Garbage collectors are pluggable so you could probably just pick one of the available implementations and tweak it.
Note: This is NOT an easy answer.
Using the Java™ Virtual Machine Tool Interface (JVM TI), the function
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
will "Force the VM to perform a garbage collection." The JVM TI is part of the JavaTM Platform Debugger Architecture (JPDA).
YES it is almost possible to forced you have to call to methods in the same order and at the same time this ones are:
System.gc ();
System.runFinalization ();
even if is just one object to clean the use of this two methods at the same time force the garbage collector to use the finalise() method of unreachable object freeing the memory assigned and doing what the finalize() method states.
HOWEVER it is a terrible practice to use the garbage collector because the use of it could introduce an over load to the software that may be even worst than on the memory, the garbage collector has his own thread which is not possible to control plus depending on the algorithm used by the gc could take more time and is consider very inefficient, you should check your software if it worst with the help of the gc because it is definitely broke, a good solution must not depend on the gc.
NOTE: just to keep on mind this will works only if in the finalize method is not a reassignment of the object, if this happens the object will keep alive an it will have a resurrection which is technically possible.
Under the documentation for OutOfMemoryError it declares that it will not be thrown unless the VM has failed to reclaim memory following a full garbage collection. So if you keep allocating memory until you get the error, you will have already forced a full garbage collection.
Presumably the question you really wanted to ask was "how can I reclaim the memory I think I should be reclaiming by garbage collection?"
You can trigger a GC from the command line. This is useful for batch/crontab:
jdk1.7.0/bin/jcmd <pid> GC.run
See :
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html
To manually Request GC (not from System.gc()) :
Go To : bin folder in JDK eg.-C:\Program Files\Java\jdk1.6.0_31\bin
Open jconsole.exe
Connect to the desired local Process.
Go To memory tab and click perform GC.
How to Force Java GC
Okay, here are a few different ways to force Java GC.
Click JConsole's Perform GC button
Use JMap's jmap -histo:live 7544 command where 7544 is the pid
Call the Java Diagnostic Console's jcmd 7544 GC.run command
Call System.gc(); in your code
Call Runtime.getRuntime().gc(); in your code
None of these work
Here's the dirty little secret. None of these are guaranteed to work. You really can't force Java GC.
The Java garbage collection algos are non-deterministic, and while all of these methods can motivate the JVM to do GC, you can't actually force it. If the JVM has too much going on and a stop-the-world operation is not possible, these commands will either error out, or they will run but GC won't actually happen.
if (input.equalsIgnoreCase("gc")) {
System.gc();
result = "Just some GC.";
}
if (input.equalsIgnoreCase("runtime")) {
Runtime.getRuntime().gc();
result = "Just some more GC.";
}
Fix the darn problem
If you've got a memory leak or object allocation problem, then fix it. Sitting around with your finger on Java Mission Control's Force Java GC button only kicks the can down the road. Profile your app with Java Flight Recorder, view the results in VisualVM or JMC, and fix the problem. Trying to force Java GC is a fools game.
.gc is a candidate for elimination in future releases - a Sun Engineer once commented that maybe fewer than twenty people in the world actually know how to use .gc() - I did some work last night for a few hours on a central / critical data-structure using SecureRandom generated data, at somewhere just past 40,000 objects the vm would slow down as though it had run out of pointers. Clearly it was choking down on 16-bit pointer tables and exhibited classic "failing machinery" behavior.
I tried -Xms and so on, kept bit twiddling until it would run to about 57,xxx something. Then it would run gc going from say 57,127 to 57,128 after a gc() - at about the pace of code-bloat at camp Easy Money.
Your design needs fundamental re-work, probably a sliding window approach.
JVM specification doesn't say anything specific about garbage collection. Due to this, vendors are free to implement GC in their way.
So this vagueness causes uncertainty in garbage collection behavior. You should check your JVM details to know about the garbage collection approaches/algorithms. Also there are options to customize behavior as well.
If you need to force garbage collection, perhaps you should consider how you're managing resources. Are you creating large objects that persist in memory? Are you creating large objects (e.g., graphics classes) that have a Disposable interface and not calling dispose() when done with it? Are you declaring something at a class level that you only need within a single method?
It would be better if you would describe the reason why you need garbage collection. If you are using SWT, you can dispose resources such as Image and Font to free memory. For instance:
Image img = new Image(Display.getDefault(), 16, 16);
img.dispose();
There are also tools to determine undisposed resources.
Another options is to not create new objects.
Object pooling is away to reduce the need GC in Java.
Object pooling is generally not going to be faster than Object creation (esp for lightweight objects) but it is faster than Garbage Collection. If you created 10,000 objects and each object was 16 bytes. That's 160,000 bytes GC has to reclaim. On the other hand, if you don't need all 10,000 at the same time, you can create a pool to recycle/reuse the objects which eliminates the need to construct new objects and eliminates the need to GC old objects.
Something like this (untested).
And if you want it to be thread safe you can swap out the LinkedList for a ConcurrentLinkedQueue.
public abstract class Pool<T> {
private int mApproximateSize;
private LinkedList<T> mPool = new LinkedList<>();
public Pool(int approximateSize) {
mApproximateSize = approximateSize;
}
public T attain() {
T item = mPool.poll();
if (item == null) {
item = newInstance();
}
return item;
}
public void release(T item) {
int approxSize = mPool.size(); // not guaranteed accurate
if (approxSize < mApproximateSize) {
recycle(item);
mPool.add(item);
} else if (approxSize > mApproximateSize) {
decommission(mPool.poll());
}
}
public abstract T newInstance();
public abstract void recycle(T item);
public void decommission(T item) { }
}
You can try using Runtime.getRuntime().gc() or use utility method System.gc() Note: These methods do not ensure GC. And their scope should be limited to JVM rather than programmatically handling it in your application.
We can trigger jmap -histo:live <pid> using the java runtime. This will force a full GC on heap to mark all the live objects.
public static void triggerFullGC() throws IOException, InterruptedException {
String pid = ManagementFactory.getRuntimeMXBean().getName().split("#")[0];
Process process = Runtime.getRuntime().exec(
String.format("jmap -histo:live %s", pid)
);
System.out.println("Process completed with exit code :" + process.waitFor());
}
I did some experimentation (see https://github.com/mikenakis/ForcingTheJvmToGarbageCollect) trying about a dozen different ways of performing a garbage collection, including ways described in this answer, and more, and I found that there is absolutely no frigging way to deterministically force the JVM to do a complete garbage collection. Even the best answers to this question are only partially successful in that the best they achieve is some garbage collection, but never a guaranteed full garbage collection.
My experimentation has showed that the following code snippet yields the best (least bad) results:
public static void ForceGarbageCollection()
{
long freeMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
for( ; ; )
{
Runtime.getRuntime().gc();
Runtime.getRuntime().runFinalization();
long newFreeMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
if( newFreeMemory == freeMemory )
break;
freeMemory = newFreeMemory;
sleep( 10 );
}
}
Where the sleep() function is as follows:
private static void sleep( int milliseconds )
{
try
{
Thread.sleep( milliseconds );
}
catch( InterruptedException e )
{
throw new RuntimeException( e );
}
}
Unfortunately, that number 10 in that sleep( 10 ) is magic; it assumes that you are doing a moderate number of memory allocations per second, which incur a moderate amount of finalization. If you are going through objects faster, then 10 might be inadequate and you may need to wait longer. You could set it to 100 to be sure, but no matter what you set it to, there will always be a chance that it will not be enough.
That having been said, in a controlled environment where that 10 is enough, this approach has been observed to consistently eliminate all unreachable objects from memory, while no other approach mentioned in this Q&A does. The experiment code I linked to on github proves so.
In my opinion, the fact that the Java Virtual Machine provides no means of performing a forced-on-demand, unconditional, deterministic, absolutely thorough, stop-the-world garbage collection makes it BROKEN.
To put it in a different way, the creators of the JVM are so full of hubris as to think that they know better than us whether we want to do that or whether we should want to do that. Don't be so arrogant. If something works as if by magic, then some means of bypassing the magic must be provided.
I wanted to force gc, because my code was frozen for a long time when it happened. The aim is to smooth the charge, by regularly cause gc.
The solutions listed doesnt forced anything in my environment.
So:
I request the memory for temporary variable,
simply, by increments,
and monitor the memory and stop the operation as soon as gc is triggered.
It works easily but you have to tune.
Runtime rt = Runtime.getRuntime();
double usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
if (usedMB > 1000) // only when necessary
{
byte[][] for_nothing = new byte[10][];
for (int k = 0; k < 10 ; k ++)
for_nothing[k] = new byte[100_000_000];
}
System.gc();
Runtime.getRuntime().gc();
Runtime.getRuntime().runFinalization();
If you are running out of memory and getting an OutOfMemoryException you can try increasing the amount of heap space available to java by starting you program with java -Xms128m -Xmx512m instead of just java. This will give you an initial heap size of 128Mb and a maximum of 512Mb, which is far more than the standard 32Mb/128Mb.
Really, I don't get you. But to be
clear about "Infinite Object Creation"
I meant that there is some piece of
code at my big system do creation of
objects whom handles and alive in
memory, I could not get this piece of
code actually, just gesture!!
This is correct, only gesture. You have pretty much the standard answers already given by several posters. Let's take this one by one:
I could not get this piece of code
actually
Correct, there is no actual jvm - such is only a specification, a bunch of computer science describing a desired behaviour ... I recently dug into initializing Java objects from native code. To get what you want, the only way is to do what is called aggressive nulling. The mistakes if done wrong are so bad doing that we have to limit ourselves to the original scope of the question:
some piece of code at my big system
do creation of objects
Most of the posters here will assume you are saying you are working to an interface, if such we would have to see if you are being handed the entire object or one item at a time.
If you no longer need an object, you can assign null to the object but if you get it wrong there is a null pointer exception generated. I bet you can achieve better work if you use NIO
Any time you or I or anyone else gets: "Please I need that horribly." it is almost universal precursor to near total destruction of what you are trying to work on .... write us a small sample code, sanitizing from it any actual code used and show us your question.
Do not get frustrated. Often what this resolves to is your dba is using a package bought somewhere and the original design is not tweaked for massive data structures.
That is very common.
FYI
The method call System.runFinalizersOnExit(true) guarantees that finalizer methods
are called before Java shuts down. However, this method is inherently unsafe
and has been deprecated. An alternative is to add “shutdown hooks” with the method
Runtime.addShutdownHook.
Masarrat Siddiqui
There is some indirect way for forcing garbage collector. You just need to fill heap with temporary objects until the point when garbage collector will execute. I've made class which forces garbage collector in this way:
class GarbageCollectorManager {
private static boolean collectionWasForced;
private static int refCounter = 0;
public GarbageCollectorManager() {
refCounter++;
}
#Override
protected void finalize() {
try {
collectionWasForced = true;
refCounter--;
super.finalize();
} catch (Throwable ex) {
Logger.getLogger(GarbageCollectorManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public int forceGarbageCollection() {
final int TEMPORARY_ARRAY_SIZE_FOR_GC = 200_000;
int iterationsUntilCollected = 0;
collectionWasForced = false;
if (refCounter < 2)
new GarbageCollectorManager();
while (!collectionWasForced) {
iterationsUntilCollected++;
int[] arr = new int[TEMPORARY_ARRAY_SIZE_FOR_GC];
arr = null;
}
return iterationsUntilCollected;
}
}
Usage:
GarbageCollectorManager manager = new GarbageCollectorManager();
int iterationsUntilGcExecuted = manager.forceGarbageCollection();
I don't know how much this method is useful, because it fills heap constantly, but if you have mission critical application which MUST force GC - when this may be the Java portable way to force GC.
I would like to add some thing here. Please not that Java runs on Virtual Machine and not actual Machine. The virtual machine has its own way of communication with the machine. It may varry from system to system. Now When we call the GC we ask the Virtual Machine of Java to call the Garbage Collector.
Since the Garbage Collector is with Virtual Machine , we can not force it to do a cleanup there and then. Rather that we queue our request with the Garbage Collector. It depends on the Virtual Machine, after particular time (this may change from system to system, generally when the threshold memory allocated to the JVM is full) the actual machine will free up the space. :D
On OracleJDK 10 with G1 GC, a single call to System.gc() will cause GC to clean up the Old Collection. I am not sure if GC runs immediately. However, GC will not clean up the Young Collection even if System.gc() is called many times in a loop. To get GC to clean up the Young Collection, you must allocate in a loop (e.g. new byte[1024]) without calling System.gc(). Calling System.gc() for some reason prevents GC from cleaning up the Young Collection.
If you are using JUnit and Spring, try adding this in every test class:
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

Categories