-7

in this code

    new Thread(new Runnable() {
        @Override
        public void run() {
            byte b[] = new byte[1024*1024*1024];

            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // just for testing
            b = null;

        }
    },"thread").start();

after 5 second 1 gigabyte of memory should be free! but it won't!

it never will!!

how can I get back memory?

burntsugar
  • 57,360
  • 21
  • 58
  • 81
  • Why do you think it should be free? It is *eligible* for GC, that doesn't mean it will be GC'd any time soon. All you can do is trust that the GC will do it eventually. – Andy Turner Nov 15 '17 at 22:06
  • @AndyTurner It's not eligible for GC. – shmosel Nov 15 '17 at 22:06
  • @shmosel where is the reference being held? – Andy Turner Nov 15 '17 at 22:07
  • That's undefined. The memory will be free whenever the GC runs which can be ... well ... whenever. It depends on your Java version and the GC configuration. In general, it will run when needed, i.e. when there's memory pressure. – Petr Janeček Nov 15 '17 at 22:08
  • @AndyTurner `b`? It's right there at the top. It isn't nulled until after the `sleep()`. – shmosel Nov 15 '17 at 22:08
  • @AndyTurner I stay for 1 hour but still nothing! – mehran rafiee Nov 15 '17 at 22:08
  • 1
    @shmosel right, but after the sleep the variable is reassigned to null, removing the last reference to `b`. OP is expecting it to be freed straight away *after* the sleep. – Andy Turner Nov 15 '17 at 22:09
  • Why would you expect anything to happen during the sleep? You still have a strong reference to the array. – shmosel Nov 15 '17 at 22:09
  • @AndyTurner Then who cares about the sleep or how long it is? – shmosel Nov 15 '17 at 22:10
  • @shmosel no idea. – Andy Turner Nov 15 '17 at 22:10
  • @mehranrafiee _"I stay for 1 hour but still nothing!"_ ... are you allocating memory in that one hour? Are you allocating enough memory for the GC to feel like actually running? If you have enough heap left, it simply will not run. There's no need. It will run when free memory starts to be low. – Petr Janeček Nov 15 '17 at 22:13
  • @PetrJaneček is there any way to deallocate this space? – mehran rafiee Nov 15 '17 at 22:21
  • 1
    @mehranrafiee Why? What are you trying to achieve, what problem are you trying to solve? The GC will eventually run, cleaning up the array. If you want the process to return some of the heap memory to the OS, then that is possible, too. Some GCs can do that, e.g. the G1 GC which is the default GC in Java 9 (but can be enabled in the previous versions, too). You could try running [`System.gc()`](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--), but that's just a heuristic, it can be implemented as a no-op depending on many things... – Petr Janeček Nov 15 '17 at 22:26
  • this is a server side application and generate a lot of threads and after at least 20 minute they will finish, but memory is still allocated. after 24 hours from 130 MB memory allocation reaches 2 GB (without file tranfer) (this is a chat socket server) – mehran rafiee Nov 15 '17 at 22:35
  • You state that you think "after 5 second 1 gigabyte of memory should be free! but it won't! it never will!" How do you know that it never will? How are you measuring if memory has been freed or not? What kind of memory are you referring to anyway? JVM heap space or system memory allocated to the JVM? – jewelsea Nov 15 '17 at 22:38
  • Perhaps your application has memory leaks, you could analyze that using a tool such as [jvisualvm](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jvisualvm.html). – jewelsea Nov 15 '17 at 22:39
  • @jewelsea because I tried for 48 hours :\ by task manager! JVM heap – mehran rafiee Nov 15 '17 at 22:47
  • 3
    Task manager doesn't measure the JVM heap, it will measure the total memory allocated to the JVM process, which is a different thing. To view the JVM heap, use a tool like jvisualvm. The jvisualvm tool can show you allocated objects within the heap and you can use it to send a signal to your the JVM to request it to remove any orphaned objects such as your `b` array after it has been set to null. If over periods after sending such signals from jvisualvm, jvisualvm reports that the space occupied by allocated objects continues to grow over time, then you have probably have memory leak. – jewelsea Nov 15 '17 at 22:53
  • @jewelsea that's help,thanks but can reduce heap size dynamically? – mehran rafiee Nov 16 '17 at 07:56
  • The JVM *may* reduce the max available heap space dynamically if it wishes to. I don't think you have much control over that process. The [client vm](https://stackoverflow.com/questions/198577/real-differences-between-java-server-and-java-client) *may* be more aggressive about releasing unused heap space back to the OS than the server vm. – jewelsea Nov 16 '17 at 09:09
  • @jewelsea thanks a lot – mehran rafiee Nov 16 '17 at 09:32
  • @mehranrafiee Aha, so this is about the process allocated memory, not the actual heap :(. You have not asked your question very clearly. What Java version are you using, what OS, which GC? Did you try a different one? Did you try meddling with the GC settings at all? You can set the max memory the heap will try to occupy in there. Also, some GCs are more prone to releasing memory back to the OS than others. G1 GC, enabled by default in Java 9, does this. The other ones ... not so much. – Petr Janeček Nov 16 '17 at 10:03

3 Answers3

4

The simple answer is eventually: no sooner, no later.

You have no direct control over when garbage will be collected. Provided the instance has no more references to it, the garbage collector will clean it up at some point.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • that's it, I want to know where is the connection that GC can't free memory – mehran rafiee Nov 15 '17 at 22:26
  • Only in one case - when there is at list one reference still in use. As example when you create an object in the method and then return it to the caller. Until reference in the caller stays GC cannot touch memory. That is why using `new` sometime is not good and having a factory to create objects is better approach. – Vadim Nov 15 '17 at 22:34
  • but in this case there is just a byte array and nothing more! – mehran rafiee Nov 15 '17 at 22:36
  • Who cares about what is it? it is an object and there is a reference to it. Your problem can be somewhere in the code. As example if code put object into any collection (list, map, set) and keeps it - so, there is a reference to it in that collection... and so on... – Vadim Nov 15 '17 at 22:39
2

In Java you cannot free memory explicitly.

It depends on JVM Garbage Collector settings. There are number of parameters for GC behavior.

Some of them are different from one JVM implementation and version to another.

But, you do not need to care about it. When there is no reference to the object anymore, memory will be cleaned when GC decides that is a time for it.

In general for all variables inside the method references gone when method completed and memory can be cleaned by GC.

You can suggest GC to run like:

...
// just for testing
b = null;
System.gc();

But it is a hint anyway. GC may run or may not.

Sometime having line like you do

b = null;

is good not only for testing, but it is not a common case.

You may try to manipulate GC settings at JVM parameters to make GC more aggressive to avoid often Full GC runs.

There are bunch of resources on Internet as example for Oracle JVM: Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide

keep in mind: different JVM may have different parameters for GC.

Vadim
  • 4,027
  • 2
  • 10
  • 26
  • There is another thing to be aware of: in some cases memory becomes "orphaned" and can be cleared only by Full GC which runs only when heap size is close to the top. Partial GC (between methods invocations) cannot pick it. Full GC is very expensive - when it runs all threads stopping and waiting until it is done. I do not remember actual cases of it, but it may happen. It is something about when creator gone before creation or such... – Vadim Nov 15 '17 at 23:00
1

there is no direct way to free memory in java. GC will run and takes care of this. If you think that you will get outofmemoryexception, then note that, java will run garbage collector to free some memory before throwing that error. Hope this helps

bajji
  • 1,271
  • 3
  • 15
  • 37
  • you mean it will remain on the memory until something else needs memory? – mehran rafiee Nov 15 '17 at 22:14
  • no.. When GC runs, the memory will be released... even when there is no memory left, before OutOfMemoryException is thrown, Java will run GC to see if anything can be released – bajji Nov 15 '17 at 22:16