java memory usage from method call - java

I'm trying to solve a problem on codeeval but am running into a problem with using too much memory. In my code there is a loop that runs many many times (~10,000^2) due to a large input that is unavoidable. I noticed that if I run the loop and do nothing on each iteration I use about 6MB of memory in total with my other code. However, if I add a simple method call in the loop that just calls a function that returns false, my memory usage jumps to 20MB.
Why is this? Shouldn't the memory allocated for each function call get deallocated after the function call is finished?
EDIT:
The full code is quite large and irrelevant to post but this snippet is what I described. If I do not include the foo() call, my code as a whole runs using 6MB of memory. If I include the foo() call, my code as a whole runs using 20MB of memory. The foo() method in my actual code does literally the same thing (return false) because I wanted to test out the memory usage.
This is for a coding challenge on codeeval so the problem should be solvable in any language they allow so java should be fine.
EDIT: I've refactored some of my code so that I could pull out an entire function to show you guys. This still produces the same result described before. The function call that produces the weird behavior is are_friends().
ArrayList<ArrayList<Integer>> graph(String[] word_list) {
ArrayList<ArrayList<Integer>> adj_list = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < word_list.length; i++) {
adj_list.add(new ArrayList<Integer>());
}
for (int i = 0; i < word_list.length; i++) {
for (int j = i + 1; j < word_list.length; j++) {
if (are_friends(word_list[i], word_list[j])) {
adj_list.get(i).add(j);
adj_list.get(j).add(i);
}
}
}
return adj_list;
}
boolean are_friends(String a, String b) {
return false;
}

If I include the foo() call, my code as a whole runs using 20MB of memory.
You should be careful about definitive claims on the memory usage of a Java program.
do you mean retained memory?
do you mean "I saw it in Task Manager/top/other process-monitoring tool"?
do you mean "I profiled it with VisualVM or similar, and that was the peak heap usage"?
With each of these approaches you'll probably be getting wildly different measurements.
One relevant indicator of memory usage would be setting the maximum heap size with -Xmx to, say, 16 MB, and seeing whether your program is able to complete error-free in one or the other of its forms. Note that this will limit only the heap and not the stack or any other support memory areas used by the JVM.
Without limiting the heap as above the JVM is free to use as much of it as it sees fit, keeping a lot of garbage around to avoid GC stalls.

The issue you are experiencing is that now it will first call a method, namely foo(), as many times as the loop runs.
And methods end up on the call stack and need extra time to be processed, for more in depth explanation you will need to google I'm afraid.
The point is that when you put the return false inside bar(), it does not manage the call stack, hence using less memory and possibly being faster.
I believe that at some point, if running on a Hotspot JVM (the default one), the JVM will inline your foo() method call, hence resulting in the behaviour as if you had a return false directly in bar(). When it optimizes, and if it does at all, depends on the JVM arguments and your specific version/system.
However even if it has optimized, the memory will already be claimed by the JVM. Even though the memory is not in use anymore by the JVM, it will refuse to give it back to your Operating System, thus you still observe the higher memory usage.

Shouldn't the memory allocated for each function call get deallocated after the function call is finished?
No. The memory used for calling a function goes on the stack. That stack is allocated when the thread starts and doesn't get freed until the thread exits.
Why is this?
I believe you have not presented all the relevant information for the problem. I just tried to reproduce the problem on CodeEval and got the same memory usage with and without the nested loop (within 500K).
It's worth noting that identical code produces a different memory result on CodeEval from run to run. I haven't seen anything deviations as wild as what you've seen, but there's clearly more factors involved than just the code.

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)

Verify object deletion in Java

In my code there are many objects created and deleted during runtime which can have long reference chains (i.e. be reachable in terms of garbage collection from many places).
In my unit test I want to verify that when I "delete" an object, e.g. remove it from the list that primarily contains it, all references to that object are deleted. To be clear: I want to verify that no reference to this object exists anymore in my application.
How can I achieve this?
So far I came only up with this (testing that a PhantomReference is enqueued):
#Test
public void test_objectX_can_be_garbage_collected() throws Exception {
ReferenceQueue<MyClass> refsToBeDeleted = new ReferenceQueue<>();
MyClass obj = new MyClass();
PhantomReference<MyClass> phantomRef = new PhantomReference<MyClass>(obj, refsToBeDeleted);
obj = null; // delete last strong reference to obj
System.out.println("Reference is enqueued:" + phantomRef.isEnqueued()); // "false"
System.gc(); // invoke garbage collection
Thread.sleep(1000L); // required - see text
System.gc(); // invoke garbage collection again
System.out.println("Reference is enqueued:" + phantomRef.isEnqueued()); // true
}
with
public static class MyClass {
}
The doc says:
public static void gc()
Runs the garbage collector.
Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.
(emphasis mine)
This is quite vague ("best effort") and seems quite non-deterministic, e.g. I have to either wait 1 second and call gc() again, or call it e.g. four times in a row for the reference to be enqueued.
Is there any way to do this properly? I want to test that objects don't persist and will eventually flood my memory after months of uptime.
Remarks:
1.) I know you should not call gc() because it's bad code. True, but I am calling it from test code to verify production code.
2.) I know that gc() is actually not deterministic from a local point of view. I'm aware of this and asking for a better alternative.
Edit:
I realized that this can be a kind of "special" unit test: If it succeeds once for a given code base, I know that this reference is garbage collected; if the unit test fails it might be because gc() didn't want to delete it, or it could not be deleted. So this test can verify that the memory is released, but it might need several attempts for that verification. However, this is "special" (read: "bad") because I would have to accept a randomly failing unit test.
AFAIK there is no way to make sure that an object has been garbage collected. Calling System.gc() will usually result in garbage collection, but not always.
I also have a infinitely running Java process - I call System.gc() at the beginning of each iteration and record the resulting amount of used memory. If this amount does not significantly change over time, I can be reasonably sure not to "leak" memory.
I've observed that when a heap dump is triggered, it usually does a full GC. If that is a policy of JVM to force GC during a Heap collection, then you can trigger a heap collection by
kill -3 pid
and see if it works.
You might need to add jvm arguments for getting a heap dump.
I do not see a problem using reference and System.gc() for testing (though I prefer weak references instead phantom ones). I do not remember any stability problems for such approach.
Reference based approach work only if you can get reference to object which may be leaked.
I have forked version of head dump analysis library from NetBeans, which I use to automate certain types of memory usage reports.
It is possible, for test code, to take heap dump of itself and inspect this dump assert specific number of objects of given type to be present.
Here you can find example of such approach.

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

Java: how much time does an empty loop use?

I am trying to test the speed of autoboxing and unboxing in Java, but when I try to compare it against an empty loop on a primitive, I noticed one curious thing. This snippet:
for (int j = 0; j < 10; j++) {
long t = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++)
;
t = System.currentTimeMillis() - t;
System.out.print(t + " ");
}
Every time I run this, it returns the same result:
6 7 0 0 0 0 0 0 0 0
Why does the first two loops always take some time, then the rest just seem to be skipped by the system?
In this answer to this post, it is said that Just-In-Time compilation will be able to optimize this away. But if so, why the first two loops still took some time?
JIT triggers AFTER a certain piece of code has been executed many times.
The HotSpot JVM will try to identify "hot spots" in your code. Hot spots are pieces of your code that are executed many many times. To do this, the JVM will "count" the executions of various instructions, and when it determines a certain piece is executed frequently, it will trigger the JIT. (this is an approximation, but it's easy to understand explained this way).
The JIT (Just-In-Time) takes that piece of code, and tries to make it faster.
The techniques used by the JIT to make your code run faster are a lot, but the one that most commonly creates confusion are :
It will try to determine if that piece of code uses variables that are not used anywhere else (useless variables), and remove them.
If you acquire and release the same lock multiple times (like calling synchronized methods of the same object), it can acquire the lock once and do all the calls in a single synchronized block
If you access members of an object that are not declare volatile, it can decide to optimize it (placing values in registers and similar), creating strange results in multi-threading code.
It will inline methods, to avoid the cost of the call.
It will translate bytecode to machine code.
If the loop is completely useless, it could be completely removed.
So, the proper answer to your question is that an empty loop, after being JITed, takes no time to execute .. most probably is not there anymore.
Again, there are many other optimizations, but in my experience these are among those that have created most headaches.
Moreover, JIT is being improved in any new version of Java, and sometimes it is even a bit different depending on the platform (since it is to some extent platform specific). Optimizations done by the JIT are difficult to understand, because you cannot usually find them using javap and inspecting bytecode, even if in recent versions of Java some of these optimizations have been moved to the compiler directly (for example, since Java 6 the compiler is able to detect and warn about unused local variables and private methods).
If you are writing some loops to test something, it is usually good practice to have the loop inside a method, call the method a few times BEFORE timing it, to give it a "speed up" round, and then perform the timed loop.
This usually triggers the JIT in a simple program like yours, even if there is no guarantee that it will actually trigger (or that it even exists on a certain platform).
If you want to get paranoid about JIT or non JIT timing (I did): make a first round, timing each execution of the loop, and wait until the timing stabilize (for example, difference from the average less than 10%), then start with your "real" timing.
The JIT doesn't kick in on a chunk of code until it determines that there is some benefit to doing so. That means the first few passes through some code won't be JITed.

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