在我的代码中找不到内存泄漏

时间:2012-01-13 11:53:16

标签: java

我有以下方法在服务器上发出HTTP Get请求,将响应解析为Java源代码。我在同一时间为多个文件执行此操作。这对于前几个文件非常有效,但在一段时间后我得到一个例外:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

行中出现异常:jp.parse(new StringReader(responseString));我认为问题是内存泄漏,因为我试图解析的文件并不是很大。只有几十行代码。但我找不到这个例外的原因。任何提示?

public void retrieveSourceCode() {
            try {
                System.out.println("Try to get: " + getSourceCodeURI());
                String responseString = RestServices.getInstance().sendGetRequestJsonTextToString(getSourceCodeURI());
                JavaSourceFactory jsf = new JavaSourceFactory();
                JavaParser jp = new JavaParser(jsf);
                jp.parse(new StringReader(responseString));
                Iterator<?> iterator = jsf.getJavaSources();
                while(iterator.hasNext()) {
                    JavaSource source =  ((JavaSource) iterator.next());
                    fileName = source.getQName().toString();
                    sourceCode = source.toString();
                }
            } catch (ClientProtocolException e) {
                fileName = "no file name";
                sourceCode = "no sourcecode available";
                e.printStackTrace();
            } catch (IOException e) {
                fileName = "no file name";
                sourceCode = "no sourcecode available";
                e.printStackTrace();
            } catch (RestServicesException e) {
                fileName = "no file name";
                sourceCode = "no sourcecode available";
                e.printStackTrace();
            } catch (RecognitionException e) {
                fileName = "no file name";
                sourceCode = "no sourcecode available";
                e.printStackTrace();
            } catch (TokenStreamException e) {
                fileName = "no file name";
                sourceCode = "no sourcecode available";
                e.printStackTrace();
            }

            if (before == null) {
                beforeSourceCode = "no before sourcecode available";
            } else {
                try {
                    String responseString = RestServices.getInstance().sendGetRequestJsonTextToString(getBeforeVersionURI());
                    JavaSourceFactory jsf = new JavaSourceFactory();
                    JavaParser jp = new JavaParser(jsf);
                    jp.parse(new StringReader(responseString));
                    Iterator<?> iterator = jsf.getJavaSources();
                    while(iterator.hasNext()) {
                        JavaSource source = (JavaSource) iterator.next();
                        beforeSourceCode = source.toString();
                    }
                } catch (ClientProtocolException e) {
                    beforeSourceCode = "no before sourcecode available";
                } catch (RecognitionException e) {
                    beforeSourceCode = "no before sourcecode available";
                    e.printStackTrace();
                } catch (TokenStreamException e) {
                    beforeSourceCode = "no before sourcecode available";
                    e.printStackTrace();
                } catch (IOException e) {
                    beforeSourceCode = "no before sourcecode available";
                    e.printStackTrace();
                } catch (RestServicesException e) {
                    beforeSourceCode = "no before sourcecode available";
                    e.printStackTrace();
                }
            }

            if (after == null) {
                afterSourceCode = "no after sourcecode available";
            } else {
                try {
                    String responseString = RestServices.getInstance().sendGetRequestJsonTextToString(getAfterVersionURI());
                    JavaSourceFactory jsf = new JavaSourceFactory();
                    JavaParser jp = new JavaParser(jsf);
                    jp.parse(new StringReader(responseString));
                    Iterator<?> iterator = jsf.getJavaSources();
                    while(iterator.hasNext()) {
                        JavaSource source = (JavaSource) iterator.next();
                        afterSourceCode = source.toString();
                    }
                } catch (ClientProtocolException e) {
                    afterSourceCode = "no after sourcecode available";
                } catch (RecognitionException e) {
                    afterSourceCode = "no after sourcecode available";
                    e.printStackTrace();
                } catch (TokenStreamException e) {
                    afterSourceCode = "no after sourcecode available";
                    e.printStackTrace();
                } catch (IOException e) {
                    afterSourceCode = "no after sourcecode available";
                    e.printStackTrace();
                } catch (RestServicesException e) {
                    afterSourceCode = "no after sourcecode available";
                    e.printStackTrace();
                }
            }

            getChangeSet().addAffectedFile(getFileName());
    }

2 个答案:

答案 0 :(得分:2)

getChangeSet().addAffectedFile()做什么?您可能想要使用已建议的探查器?

坚持下去吗?此外,您可能希望将该方法拆分为多个部分。

答案 1 :(得分:1)

为什么要继续使用相同的处理代码重复这些catch块?我会抓住Exception一次并完成它。其余的人什么都不做,只会增加视觉上的混乱。

但这不是你问题的答案......

这些课程是您的,还是来自图书馆?我猜它是Apache JAXMe库。

如果您使用的是Sun JVM,可以下载Visual VM 1.3.3,安装所有插件,打开它,然后开始您的流程以了解正在发生的事情。它将通过生成,CPU,线程等向您展示内存。这是一个很棒的工具。

为什么不尝试添加finally块并清除阵列?你没有在电话之间保留这些数据,对吗?如果是,其他呼叫者如何查找并使用结果?也许WeakHashMap可能是你的解决方案。如果需要,您将为JVM提供清理的机会。

你应该小心线程安全。 Servlet是共享的,所以如果你挂在那个可变对象上,你需要担心同步。