Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Runtime memory increase when migrating a Swing application from Java 6 to Java 7 Update 11

We are facing a performance issue once the Java Swing application is moved from Java 6 32 bit to Java 7 32 bit update 11. Can anyone provide some clue on this ?

The application is using Java Web-start technology and the server is Tomcat 7. The client application is consuming 1GB of memory, so the screen is freezing out.

We are exchanging serialized objects, following is the code:

Object object = connection.sendCommand(command); // exchanging serialized object            

public class ConnectionImpl implements Connection {
    public Object sendCommand(Command command) throws Exception {
        URL url = new URL(System.getProperty("serverUrl"));
        URLConnection connection = url.openConnection();
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
        oos = new ObjectOutputStream(new BufferedOutputStream(connection
                    .getOutputStream()));
        oos.writeObject(command);
        oos.flush();
        InputStream inputStream = connection.getInputStream();
        ZipInputStream zip = new ZipInputStream(inputStream);
        if (zip.getNextEntry() != null) {
            ois = new ObjectInputStream(zip);
            object = ois.readObject();
        }
        zip.close();
    }
}

// The serialized class
public class CommandImpl implements Command, Serializable {
    private String serviceName;
    private String methodName;
    private Map<String, Object> parameterMap;

// followed by getter & setters
}
  • Client Machine: Windows 7 32 bit, Java 7 update 11 32 bit
  • Server Machine: Windows 64 bit 2008 R2 Enterprise Server, Java 7 update 11 64 bit

There is no change in the code only the JVM is updated.

I have taken the memory snapshot for JDK 1.6 and JDK 1.7 using Java VisualVM, following is the link to rar file which contains the snapshots:

Memory Snapshots using Java VisualVM Heap Dump using Java VisualVM

The NetBeans IDE provides an option to migrate the code from Java 6 to Java 7. Following is the link regarding this:

https://netbeans.org/kb/docs/java/editor-inspect-transform.html#convert

Will it be a good option for migrating the entire source code from Java 6 to Java 7 without any issue? Or anyone feels that it might create some issue ? And if we do so, whether we can solve this performance issue up-to some extend?

like image 786
Leejoy Avatar asked Jun 07 '13 11:06

Leejoy


2 Answers

The ObjectOutputStream oos gets constructed in the method but it doesn't look like you ever close it. Closing the stream will free memory.

When does ObjectOutputStream get garbage collected? ObjectOutputStream and ObjectInputStream keep read and written objects in memory. That will look like a memory leak.

I'd suggest you add finally blocks to be sure the Streams get closed. I can't tell what the lifetime of the serialized objects is from what you posted but you might benefit from using the readUnshared and writeUnshared methods.

You wrote:

Will it be a good option for migrating the entire source code from Java 6 to Java 7 without any issue? Or anyone feels that it might create some issue ? And if we do so, whether we can solve this performance issue up-to some extend?

You won't benefit from using a tool to update the code to 1.7. If you did that you would no longer be able to run your code in 1.6. I recommend running Netbean's "Performance" inspections. Also, I highly recommend running FindBugs against your codebase.

Heapdumps

  • The jdk 1.7 dump was taken of the heap when 53M was used.
  • The jdk 1.6 dump was taken when 61M were used.

The heapdumps you posted aren't that helpful because it looks like they were taken before memory was an issue. You need to take a heapdump while the system is using lots of memory so that you can examine the dump and find out where the memory is being used.

Add the -XX:+HeapDumpOnOutOfMemoryError jvm option. With this option java will automatically take its own heapdump when it runs out of memory.

Snapshots

** Although your snapshots archive has four files in it, two of the files are duplicates with different names. Look at the sizes and the checksums and you will see they are the same. **

The snapshots are more informative but they also seem to have been taken before much memory was used.

The 1.7 snapshot has many more String instances.

The 1.6 snapshot looks like this: visualvm iamge

The 1.7 snapshot looks like: enter image description here

String.substring no longer shares an underlying character array. That can be a pretty big difference in code that does lots of String manipulation.

Those char[] hold the actual data in your String objects. I would take a closer look at what objects hold Strings and how those Strings get constructed.

like image 150
Ryan Avatar answered Sep 23 '22 20:09

Ryan


I think there are too many possible explanations and too little hard evidence in the Question to say what the problem is.

I suggest that you:

  1. increase the heap size to get it to the point where application starts on Java 7, then
  2. run a memory profiler on the Java 7 and Java 6 versions to figure out why Java 7 is using significantly more memory.

Notes:

  • Going from a Java 6 32 bit to Java 7 64 bit client-side execution platform, would be enough to explain the increased memory usage. (But apparently the client side OS is 32 bit, so that eliminates that explanation, though your Question actually contradicts itself on this point ...)
  • Recompiling using a Java 7 compiler (32 bit or 64 bit) is unlikely to make any difference.
  • The server platform is unlikely to be relevant.
like image 20
Stephen C Avatar answered Sep 21 '22 20:09

Stephen C