将Swing应用程序从Java 6迁移到Java 7 Update 11时,运行时内存会增加

Lee*_*joy 7 java memory swing java-web-start

一旦Java Swing应用程序从Java 6 32位转移到Java 7 32位更新11,我们就会遇到性能问题.任何人都可以提供一些线索吗?

该应用程序使用Java Web-start技术,服务器是Tomcat 7.客户端应用程序占用1GB内存,因此屏幕冻结.

我们正在交换序列化对象,以下是代码:

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
}
Run Code Online (Sandbox Code Playgroud)
  • 客户端机器: Windows 7 32位,Java 7更新11位32位
  • 服务器计算机: Windows 64位2008 R2企业服务器,Java 7更新11 64位

只有JVM更新后,代码才会发生变化.

我使用Java VisualVM获取了JDK 1.6和JDK 1.7的内存快照,以下是包含快照的rar文件的链接:

使用Java VisualVM使用Java VisualVM 堆转储的内存快照

NetBeans IDE提供了将代码从Java 6迁移到Java 7的选项.以下是有关此内容的链接:

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

将整个源代码从Java 6迁移到Java 7是否是一个很好的选择?或者任何人都认为它可能会产生一些问题?如果我们这样做,我们能否在一定程度上解决这个性能问题?

Rya*_*yan 6

ObjectOutputStream oos在方法中构造,但它看起来并不像你关闭它.关闭流将释放内存.

ObjectOutputStream什么时候收集垃圾? ObjectOutputStream和ObjectInputStream将读取和写入的对象保留在内存中.这看起来像是内存泄漏.

我建议你添加finally块以确保Streams关闭.我不知道序列化对象的生命周期是什么来自您发布的内容,但您可能会从使用readUnshared和writeUnshared方法中受益.

你写了:

将整个源代码从Java 6迁移到Java 7是否是一个很好的选择?或者任何人都认为它可能会产生一些问题?如果我们这样做,我们能否在一定程度上解决这个性能问题?

使用工具将代码更新为1.7将无法受益.如果你这样做,你将无法再在1.6中运行你的代码.我建议运行Netbean的"性能"检查.此外,我强烈建议您针对您的代码库运行FindBugs.

Heapdumps

  • 当使用53M时,从堆中获取jdk 1.7转储.
  • 当使用61M时,采用了jdk 1.6转储.

您发布的堆转储没有那么有用,因为它看起来像是在内存出现问题之前拍摄的.在系统使用大量内存时需要使用heapdump,以便检查转储并找出内存的使用位置.

添加-XX:+HeapDumpOnOutOfMemoryErrorjvm选项.使用此选项,当内存不足时,java将自动获取自己的heapdump.

快照

**虽然您的快照存档中有四个文件,但其中两个文件是不同名称的重复文件.查看大小和校验和,您将看到它们是相同的.**

快照提供了更多信息,但它们似乎也在使用大量内存之前拍摄.

1.7快照有更多的String实例.

1.6快照如下所示: visualvm iamge

1.7快照看起来像: 在此输入图像描述

String.substring不再共享基础字符数组.对于执行大量字符串操作的代码而言,这可能是一个非常大的差异.

那些char []保存String对象中的实际数据.我会仔细看看哪些对象包含字符串以及这些字符串是如何构造的.


Ste*_*n C 5

我认为问题中有太多可能的解释和太少的确凿证据表明问题是什么.

我建议你:

  1. 然后,增加堆大小以使其达到应用程序在Java 7上启动的程度
  2. 在Java 7和Java 6版本上运行内存分析器,以找出Java 7使用更多内存的原因.

笔记:

  • 从Java 6 32位到Java 7 64位客户端执行平台,足以解释增加的内存使用量.(但显然客户端操作系统是32位,因此消除了这种解释,尽管你的问题在这一点上实际上是矛盾的......)
  • 使用Java 7编译器(32位或64位)进行重新编译不太可能有任何区别.
  • 服务器平台不太可能相关.