0

I've got problem with releasing memory by jvm. I know that java release memory of thread resoruces after its exit from run method. And other objects are deleting by garbage collector when they don't have referencees with some exceptions like windows/frames. Why in below code gc doesn't release memory of byte array despite of threads end their work? I know System.gc() is only suggestion for gc but i use it just in case and assigning null for byte array reference is unnecessary.
Below code is only example and i've got real problem in my client-server application in similar case when server send files to clients.

 private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {                                         
   int j=0;
    for (int i=0;i<5;i++){
       try {
           Thread.sleep(2000);
       } catch (InterruptedException ex) {
           Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
       }
       j++;
       new Thread(new Runnable(){
           public void run(){
               byte[] bytes=new byte[1024*1024*100];
               try {
                   Thread.sleep(15000);
               } catch (InterruptedException ex) {
                   Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
               }
               System.out.println("exiting "+Thread.currentThread().getName());
               bytes=null;
               System.gc();
           }
       }, ""+j).start();

   }
System.gc();     
} 

I leave above problem and go to be practical. Earlier there was loading whole file to one byte array and sending it using writeObject(), but it causes memory problems. Look at that code:

                BufferedOutputStream bos = null;                    
                byte[] bytes;
                int count;
                for (int i = 0; i < filesToUpdate.size(); i++) {                      
                    if (mapp.get(filesToUpdate.get(i)) == null) {
                        addNewFile(filesToUpdate.get(i));
                    }                        
                    bos = new BufferedOutputStream(new FileOutputStream(new File(filesToUpdate.get(i))));                        
                    long bufferSize = ois.readLong();                        
                    ous.writeObject(2);
                    ous.flush();                                                                             
                    bytes =new byte[8192];                       
                    while ((count=ois.read(bytes))>0){
                        bos.write(bytes, 0, count);                
                    }
                    bos.flush();
                    bos.close();                                                                  
                    ous.writeObject(3);
                    ous.flush();                        
                }
                ois.readObject();                    
                updateRevision(mapp, filesToUpdate);

It's client side which receives files. READ METHOD BLOCKS in first file after it received last packet. And here is server side:

       int count;           
        File file;
        FileInputStream fis=null;
        byte[] bytes;
        for (int i=0;i<filesForPatch.size();i++){
            if (pc.getWhat()==0)
                path="admin/";
            else path="client/";
            path+=filesForPatch.get(i);
            file=new File(path);                           
            long buffSize=file.length();
            ous.writeLong(buffSize);
            ous.flush();                                             
            ois.readObject();               
            fis=new FileInputStream(file);
            bytes=new byte[8192];
            while ((count=fis.read(bytes))>0){
                ous.write(bytes, 0, count);
            }
            ous.flush();
            fis.close();
            ois.readObject();             
        }    

Any ideas how to solve this problem?

8
  • How did you check that Java is not releasing the memory of the byte array? Basically, can you post something to support your claim?? Commented Mar 29, 2015 at 10:54
  • I check it by windows task manager. Commented Mar 29, 2015 at 10:57
  • Can you elaborate on what stats of the windows task manager got you to believe that it is the byte array that is causing the memory leak and not some other part of your program, or a different application on your system all-together? Commented Mar 29, 2015 at 10:59
  • It's very simple program there is only above code and frame with button creating. So what else can do that memory leak? Commented Mar 29, 2015 at 11:05
  • That's right. So windows task manager is not telling you it's the byte array. You feel that it's the byte array that's the culprit right? Why do you feel the byte array is the culprit? Commented Mar 29, 2015 at 11:05

2 Answers 2

1

The info you get from the Windows Task Manager doesn't mean a lot. The JVM dynamically sizes the heap according to many factors, throughput being the first concern. The heap size is never exactly equal to the actual memory allocated by reachable objects.

If you want to observe the effects of garbage collection, then connect to your JVM with VisualVM. For best effects install the VisualGC plugin and open its tab, there you will be able to observe the changes in the size of all generations in real time. Garbage collections will be immediately reflected in the shown occupancy and you'll also be able to notice when the heap itself is being resized (rarely).

Sign up to request clarification or add additional context in comments.

5 Comments

How i solve this problem in my server-client application. I load file to byte array and send it to client. During every file sending jvm allocate ram at size about file size and doesn't release its. Server works in infinite loop and after some clients download files memory for server is about few gigabytes and application throws no more available memory exception.
That description sounds like a memory leak, it is not an issue with the garbage collector. You have to see why the arrays are staying reachable all the time. But BTW copying the whole file to memory is not the optimal approach, you should stream the file directly from disk to network, then from network to file at the server side. Only a buffer's worth of data should be in RAM at any point in time.
I firstly do like you said but i have problem with blocking read of input stream after stream receives last packet. Available() method doesn't solve the problem because it gets data from next file i send and saves it to previous file.
Any problem you may have had is due to incorrect API usage, like not properly closing the output stream at the sending side.
Look at my first post (question). I paste my code containing problem with stream.
0

for (int i=0;i<5;i++){

This most likely is an insufficient amount of time for the GC to settle into a stable state for heap size. If you were to run this 10000 times you would see that it eventually settles on a stable amount of memory.

So your example is not a reduced test case of your client-server program.

So if there is an actual memory in your application it is not possible to find it based on that example.

The easiest way to find a leak is to let the program run for a while and then inspect a heap dump with a memory profiler such as yourkit, jprofiler or eclipse's MAT

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.