zoukankan      html  css  js  c++  java
  • java.lang.OutOfMemoryError: Java heap space错误及处理办

    默认方式启动Eclipse时,有关启动时JVM参数是在Eclipse安装目录下的eclipse.ini文件中指定的.在命令行下,也可以通过参数-vmargs来达到此目的.其命令格式为:eclipse -vmargs <JVM参数设置>.举例来说,命令eclipse -vmargs -Xmx512M用来设置Eclipse启动时JVM的最大堆内存(heap memory)

      -vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M

      这里有几个问题:

      1. 各个参数的含义什么?

      2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?

      3. 为何将上面的参数写入到eclipse.ini文件Eclipse没有执行对应的设置?

      下面我们一一进行回答

      1. 各个参数的含义什么?

      参数中-vmargs的意思是设置JVM参数,所以后面的其实都是JVM的参数了,我们首先了解一下JVM内存管理的机制,然后再解释每个参数代表的含义.

      堆(Heap)和非堆(Non-heap)内存

      按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创建的.”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”.可以看出JVM主要管理两种类型的内存:堆和非堆.简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中.

      堆内存分配

      JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4.默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制.因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小.

      非堆内存分配

      JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4.

      JVM内存限制(最大值)

      首先JVM内存限制于实际的最大物理内存(废话!呵呵),假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系.简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了.

      2. 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?

      通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统.所以说设置VM参数导致程序无法启动主要有以下几种原因:

      1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;

      2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等.说到实际物理内存这里需要说明一点的是,如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了.

      3. 为何将上面的参数写入到eclipse.ini文件Eclipse没有执行对应的设置?

      那为什么同样的参数在快捷方式或者命令行中有效而在eclipse.ini文件中是无效的呢?这是因为我们没有遵守eclipse.ini文件的设置规则:

      参数形如“项 值”这种形式,中间有空格的需要换行书写,如果值中有空格的需要用双引号包括起来.比如我们使用-vm C:Javajre1.6.0injavaw.exe参数设置虚拟机,在eclipse.ini文件中要写成这样:

      -vm

      C:Javajre1.6.0injavaw.exe

      按照上面所说的,最后参数在eclipse.ini中可以写成这个样子:

      -vmargs

      -Xms128M

      -Xmx512M

      -XX:PermSize=64M

      -XX:MaxPermSize=128M

      实际运行的结果可以通过Eclipse中“Help”-“About Eclipse SDK”窗口里面的“Configuration Details”按钮进行查看.

      另外需要说明的是,Eclipse压缩包中自带的eclipse.ini文件内容是这样的:

      -showsplash

      org.eclipse.platform

      --launcher.XXMaxPermSize

      256m

      -vmargs

      -Xms40m

      -Xmx256m

      其中–launcher.XXMaxPermSize(注意最前面是两个连接线)跟-XX:MaxPermSize参数的含义基本是一样的,我觉得唯一的区别就是前者是eclipse.exe启动的时候设置的参数,而后者是eclipse所使用的JVM中的参数.其实二者设置一个就可以了,所以这里可以把 –launcher.XXMaxPermSize和下一行使用#注释掉.

      3. 其他的启动参数. 如果你有一个双核的CPU,也许可以尝试这个参数:

      -XX:+UseParallelGC

      让GC可以更快的执行.(只是JDK 5里对GC新增加的参数)

      堆大小设置

      JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可用虚拟内存限制;系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G;64为操作系统对内存无限制.我在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m.

      典型设置:

      java -Xmx3550m -Xms3550m -Xmn2g -Xss128k

      -Xmx3550m:设置JVM最大可用内存为3550M.

      -Xms3550m:设置JVM促使内存为3550m.此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存.

      -Xmn2g:设置年轻代大小为2G.整个堆大小=年轻代大小 + 年老代大小 + 持久代大小.持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小.此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8.

      -Xss128k:设置每个线程的堆栈大小.JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K.更具应用的线程所需内存大小进行调整.在相同物理内存下,减小这个值能生成更多的线程.但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右.

      java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0

      -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代).设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5

      -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的大小比值.设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6

      -XX:MaxPermSize=16m:设置持久代大小为16m.

      -XX:MaxTenuringThreshold=0:设置垃圾最大年龄.如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代.对于年老代比较多的应用,可以提高效率.如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论.

      回收器选择

      JVM 给了三种选择:串行收集器、并行收集器、并发收集器,但是串行收集器只适用于小数据量的情况,所以这里的选择主要针对并行收集器和并发收集器.默认情况下,JDK5.0以前都是使用串行收集器,如果想使用其他收集器需要在启动时加入相应参数.JDK5.0以后,JVM会根据当前系统配置进行判断.

      吞吐量优先的并行收集器

      如上文所述,并行收集器主要以到达一定的吞吐量为目标,适用于科学技术和后台处理等.

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/Evil-Rebe/p/6054847.html
Copyright © 2011-2022 走看看