请教一下高人:
我在使用ANT的API进行编译的时候,总是会出现内存益处的错误:"java.lang.OutOfMemoryError: Java heap space"
可是我已经在启动项里面对内存进行了绝对够用的设置:
-DANT_OPTS=-Xmx512m -Xmx800M -Xms800m -Xmn256m我用jconsole进行监控发现我程序的内存使用量没超过200M,有些异常的是有一条eden的监控数据:
eden space 139264K, 100% used [0x07c30000, 0x10430000, 0x10430000)
from space 17408K,   4% used [0x10430000, 0x104df0c0, 0x11530000)
to   space 17408K,   0% used [0x11530000, 0x11530000, 0x12630000)
具体这样会对程序有什么影响我就不太清楚了。或许是因为其他原因,哪位朋友知道的话请指教一二,能解决这个问题的话,我有的分要多少都给。
我的程序是这样:
Javac vJavaCompiler = new org.apache.tools.ant.taskdefs.Javac();
.......略一些
vJavaCompiler.setOptimize(false);
vJavaCompiler.setDebug(true);
vJavaCompiler.setFailonerror(true);
vJavaCompiler.setEncoding("utf-8");
vJavaCompiler.setNowarn(true);
vJavaCompiler.setTarget("1.5");
vJavaCompiler.setExcludes("**/*.smap autoconf/* **/*.txt **/*.xml **/*.prop*");
vJavaCompiler.setFork(true);
vJavaCompiler.setSrcdir(vSrcPath);
vJavaCompiler.setDestdir(vDestFile);
.......设置classpath和srcpath等
vJavaCompiler.execute();
-------------------------------------------------------
详细的错误信息如下:
    [Javac] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    [Javac]  at java.util.jar.Manifest.read(Manifest.java:165)
    [Javac]  at java.util.jar.Manifest.<init>(Manifest.java:52)
    [Javac]  at java.util.jar.JarFile.getManifestFromReference(JarFile.java:163)
    [Javac]  at java.util.jar.JarFile.getManifest(JarFile.java:145)
    [Javac]  at sun.misc.URLClassPath$JarLoader$1.getManifest(URLClassPath.java:624)
    [Javac]  at java.net.URLClassLoader.defineClass(URLClassLoader.java:221)
    [Javac]  at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
    [Javac]  at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    [Javac]  at java.security.AccessController.doPrivileged(Native Method)
    [Javac]  at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    [Javac]  at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    [Javac]  at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
    [Javac]  at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
    [Javac]  at java.util.ResourceBundle.loadBundle(ResourceBundle.java:1053)
    [Javac]  at java.util.ResourceBundle.findBundle(ResourceBundle.java:928)
    [Javac]  at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:743)
    [Javac]  at java.util.ResourceBundle.getBundle(ResourceBundle.java:549)
    [Javac]  at com.sun.tools.javac.main.Main.initResource(Main.java:674)
    [Javac]  at com.sun.tools.javac.main.Main.getText(Main.java:690)
    [Javac]  at com.sun.tools.javac.main.Main.getLocalizedString(Main.java:662)
    [Javac]  at com.sun.tools.javac.main.Main.resourceMessage(Main.java:649)
    [Javac]  at com.sun.tools.javac.main.Main.compile(Main.java:601)
    [Javac]  at com.sun.tools.javac.main.Main.compile(Main.java:544)
    [Javac]  at com.sun.tools.javac.Main.compile(Main.java:67)
    [Javac]  at com.sun.tools.javac.Main.main(Main.java:52)
Compile failed; see the compiler error output for details.
at org.apache.tools.ant.taskdefs.Javac.compile(Javac.java:1079)
at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:882)
at cn.tencent.toolbox.func.JspLocalCompiler.doJspJavaCompile(JspLocalCompiler.java:295)
at cn.tencent.toolbox.func.JspLocalCompiler.doJspcCompile(JspLocalCompiler.java:215)
at cn.tencent.toolbox.func.JspLocalCompilerUI$6.run(JspLocalCompilerUI.java:239)
at java.lang.Thread.run(Thread.java:595)

解决方案 »

  1.   

    可是我已经在启动项里面对内存进行了绝对够用的设置:
    -DANT_OPTS=-Xmx512m -Xmx800M -Xms800m -Xmn256m 这些都是啥啊?怎么还有那么多重复的?java的参数是-Xmx1024m 就可以了。 至于你的ANT参数,我不清楚了,你用这个看看,其它的都删除吧
      

  2.   

    关于启动参数是这个样子:
    (1)我一开始是只加了-Xmx参数的,但其实这个程序+虚拟机一共也根本用不了100M内存,设再大也是没用.
    (2)于是我开始上网找有没有相关的参数设定,才把那些启动参数逐一加上去,结果也是没用
    (3)我用jconsole观察内存使用,有时候发现有两个参数会比较异常 
    eden space 1088K, 100% used [0x03dc0000, 0x03ed0000, 0x03ed0000)
    the space 14080K,  99% used [0x43dc0000, 0x44b68a28, 0x44b68c00, 0x44b80000) No shared spaces configured.
    (4)再有就是我看ANT的JavaC代码看到ANT的API会起一个新进程,不知道会不会有影响,请各位再帮忙看下,有这方面经验的朋友不吝指教。
      

  3.   

    一般是这样处理的,
    你编译选择的jre是工作空间的还是其他的?
    在elipse首选项里对应的jre,然后加启动参数-xmx512
      

  4.   

    我是直接用命令行启动的这个程序的,选择的jre是JDK目录/jre,并不是在eclipse里启动的.
    我在网上基本找遍了控制内存的启动参数,实验都没效果,郁闷
      

  5.   

    自己发现了一个问题,调用ANT的API编译的话,ANT的API会另启动一个进程,下面是JPS的结果:
    thinkpad-t400-2:~ # jps
    5762 Main
    5746 JspLocalCompiler然后看那个Main进程发现这个内存溢出可能的问题:
     num     #instances         #bytes  class name
    ----------------------------------------------
       1:        276195        8838240  com.sun.tools.javac.tree.JCTree$JCIdent
       2:        485861        7773776  com.sun.tools.javac.util.List
       3:        152366        6365032  [C
       4:        169623        5427936  com.sun.tools.javac.tree.JCTree$JCLiteral
       5:        158884        5084288  com.sun.tools.javac.tree.JCTree$JCFieldAccess
       6:        101546        4061840  com.sun.tools.javac.tree.JCTree$JCMethodInvocation后面的问题改成如何设定使得ANT另启动的那个进程不会内存益处,分值不变
      

  6.   

    Java Heap分为3个区,Young,Old和Permanent。
    Young保存刚实例化的对象。
    当该区被填满时,GC会将对象移到Old区。
    Permanent区则负责保存反射对象。JVM的Heap分配可以使用-X参数设定,-Xms 初始Heap大小  
    -Xmx java heap最大值  
    -Xmn young generation的heap大小 
    JVM有2个GC线程。第一个线程负责回收Heap的Young区。第二个线程在Heap不足时,遍历Heap,将Young 区升级为Older区。
    Older区的大小等于-Xmx减去-Xmn,不能将-Xms的值设的过大,因为第二个线程被迫运行会降低JVM的性能。
    1.增加Heap的大小虽然会降低GC的频率,但也增加了每次GC的时间。并且GC运行时,所有的用户线程将暂停,也就是GC期间,Java应用程序不做任何工作。
    2.Heap大小并不决定进程的内存使用量。进程的内存使用量要大于-Xmx定义的值,因为Java为其他任务分配内存,例如每个线程的Stack等。Stack的设定,每个线程都有他自己的Stack。-Xss 每个线程的Stack大小 Stack的大小限制着线程的数量。如果Stack过大就好导致内存溢漏。-Xss参数决定Stack大小,例如-Xss1024K。如果Stack太小,也会导致Stack溢漏。
    =========================
    你的 -Xmx512m -Xmx800M -Xms800m -Xmn256m
    只会加载一个吧,如果是前一个,那么你的初始化heap比你的最大heap大,
    只有设计jvm的人才会知道会在什么时候会发生什么事
      

  7.   

    对内存进行了绝对够用的设置: 
    -DANT_OPTS=-Xmx512m -Xmx800M -Xms800m -Xmn256m 
    这些都是啥啊?怎么还有那么多重复的? 
    java的参数是 
    -Xmx1024m 就可以了。 至于你的ANT参数,我不清楚了,你用这个看看,其它的都删除吧