java虚拟机的内存配置

来源:互联网 发布:apache性能测试工具 编辑:程序博客网 时间:2024/05/19 00:36
今天早上一大早开Myeclipse,却怎么也打不开。提示:
could not create the java virtual machine.

试了几次开启均失败。于是网上查了下资料。没想到下面这个方法马上就解决了问题,在此记录下:

在C:\Program Files\MyEclipse 6.0\eclipse安装目录下,有个eclipse.ini的文件,用UltrEdit打开内容如下:

 -showsplash
com.genuitec.myeclipse.product
--launcher.XXMaxPermSize
256m
-vmargs
-Xms128m
-Xmx512m
-Duser.language=en
-XX:PermSize=128M   
-XX:MaxPermSize=256M

 

我把最后两行修改成:

-XX:PermSize=64M   
-XX:MaxPermSize=128M

 

就可以了。

个中原因,我百度了一下,现摘全文如下:

 

-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:\Java\jre1.6.0\bin\javaw.exe参数设置虚拟机,在eclipse.ini文件中要写成这样: -vm C:\Java\jre1.6.0\bin\javaw.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新增加的参数)

 

=============================================================================================================================

java虽然是自动回收内存,但是应用程序,尤其服务器程序最好根据业务情况指明内存分配限制。否则可能导致应用程序宕掉。

举例说明含义:-Xms128m

表示JVM Heap(堆内存)最小尺寸128MB,初始分配

-Xmx512m

表示JVM Heap(堆内存)最大允许的尺寸256MB,按需分配。

说明:如果-Xmx不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM不是Throwable的,无法用try…catch捕捉。

PermSize和MaxPermSize指明虚拟机为java永久生成对象(Permanate generation)如,class对象、方法对象这些可反射(reflective)对象分配内存限制,这些内存不包括在Heap(堆内存)区之中。

-XX:PermSize=64MB 最小尺寸,初始分配

-XX:MaxPermSize=256MB 最大允许分配尺寸,按需分配

过小会导致:java.lang.OutOfMemoryError: PermGen space

 

MaxPermSize缺省值和-server -client选项相关。

-server选项下默认MaxPermSize为64m

-client选项下默认MaxPermSize为32m

 

相比Perm Size (permanent generation size)和 Heap Size,OutOfMemoryError 要更常见一些。一般当你遇到OutOfMemoryError 问题时,很多人会告诉你用下面种方法来解决问题:

 

•添加/调整启动参数-Xms 和 -Xmx,用以增大Heap Size

•以server 方式启动JVM,用以提高JVM”运行期”的执行效率

•检查程序,看是否有不合理的new 操作导致大量不必要的内存消耗

上面两种方法确能解决许多普通问题,但有时即使你设置了很大的Heap Size(比如-Xms128m -Xmx1024m),OutOfMemoryError 仍可能会出现,这时Perm Size 就可能与你有关了。

 

参见:

 

•http://lists.canoo.com/pipermail/webtest/2004q3/002460.html

•http://www.raibledesigns.com/page/rd?anchor=how_do_you_determine_a

•http://forum.java.sun.com/thread.jspa?threadID=775925

Perm Size 是部分与-Xms/mx 所指定的heap size无关的内存空间(default: 32M for client, 64M for server),所以即使你设置了再大的ms/mx 值,也仍然存在OutOfMemoryError 隐患。Perm Size 中存放了class 的metadata 等(google for more information)信息,如果你的应用中采用了 Spring、Hibernate 或 Tapestry 等基于 reflection 和 proxying 的框架时,你就很有可能会遇到OutOfMemoryError。

 

如果是这种情况那就考虑在启动时加入如下参数吧:-XX:PermSize=128m

 

至于如何选择最合适的PermSize值,可以参考

http://www.raibledesigns.com/page/rd?anchor=how_do_you_determine_a

里面提到了分析最优PermSize 值的几种方法。

 

注意:并非所有JVM vendor 开发的JVM 都支持/存在PermSize 问题。

 

另,OutOfMemoryError 的多与JVM 的 GC 有关,选择合适的GC 策略,合理设置启动选项会有很大帮助,参见:http://geniil.spaces.live.com/blog/cns!81B15F02616BA25C!204.entry

 

另在工作环境里可以使用jrocket

===============================================================================================================

一、内存溢出的类型

1、java.lang.OutOfMemoryError: PermGen space

       JVM管理两种类型的内存,堆和非堆。堆是给开发人员用的上面说的就是,是在JVM启动时创建;非堆是留给JVM自己用的,用来存放类的信息的。它和堆不同,运行期内GC不会释放空间。

       PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。

       设置参数:-XX:PermSize=128M  (初始值) -XX:MaxPermSize=256m (最大值)

 

       2、java.lang.OutOfMemoryError: Java heap space

       第一种情况是个补充,主要存在问题就是出现在这个情况中。其默认空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。如果内存剩余不到40%,JVM就会增大堆到Xmx设置的值,内存剩余超过70%,JVM就会减小堆到Xms设置的值。所以服务器的Xmx和Xms设置一般应该设置相同避免每次GC后都要调整虚拟机堆的大小。

       注意:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。

       产生过程:java内存堆不足时,会不断调用GC,若连续回收都解决不了内存堆不足的问题时,就会报out of memory错误

       在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。

 

二、垃圾回收

       新创建的对象被分配到New区,当该区被填满时会被GC辅助线程移到Old区,当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。

 

 

三、JVM内存区域组成

       简单的说java中的堆和栈

java把内存分两种:一种是栈内存,另一种是堆内存

1。在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配;

2。堆内存用来存放由new创建的对象和数组

在函数(代码块)中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间;在堆中分配的内存由java虚拟机的自动垃圾回收器来管理

堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢;

栈的优势是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的无灵活性。

 

java堆分为三个区:New、Old和Permanent

GC有两个线程:

新创建的对象被分配到New区,当该区被填满时会被GC辅助线程移到Old区,当Old区也填满了会触发GC主线程遍历堆内存里的所有对象。Old区的大小等于Xmx减去-Xmn

java栈存放

栈调整:参数有+UseDefaultStackSize -Xss256K,表示每个线程可申请256k的栈空间

每个线程都有他自己的Stack

 

四、JVM内存参数设置

提示1:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。

提示2:JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。

提示3:如果Xms超过了Xmx值,或者堆最大值和非堆最大值的总和超过了物理内存或者操作系统的最大限制都会引起服务器启动不起来。

提示:设置NewSize、MaxNewSize相等,"new"的大小最好不要大于"old"的一半,原因是old区如果不够大会频繁的触发"主" GC ,大大降低了性能

JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;

由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

 

五、性能检查工具使用

       JProfiler工具主要用于检查和跟踪系统(限于Java开发的)的性能。JProfiler可以通过时时的监控系统的内存使用情况,随时监视垃圾回收,线程运行状况等手段,从而很好的监视JVM运行情况及其性能。

 

 

 

六、不健壮代码胡特征及解决办法

1、尽早释放无用对象的引用。好的办法是使用临时变量的时候,让引用变量在退出活动域后,自动设置为null,暗示垃圾收集器来收集该对象,防止发生内存泄露。

对于仍然有指针指向的实例,jvm就不会回收该资源,因为垃圾回收会将值为null的对象作为垃圾,提高GC回收机制效率;

2、我们的程序里不可避免大量使用字符串处理,避免使用String,应大量使用StringBuffer,每一个String对象都得独立占用内存一块区域;

String str = "aaa";

String str2 = "bbb";

String str3 = str + str2;//假如执行此次之后str ,str2以后再不被调用,那它就会被放在内存中等待Java的gc去回收,程序内过多的出现这样的情况就会报上面的那个错误,建议在使用字符串时能使用StringBuffer就不要用String,这样可以省不少开销;

3、尽量少用静态变量,因为静态变量是全局的,GC不会回收的;

4、避免集中创建对象尤其是大对象,JVM会突然需要大量内存,这时必然会触发GC优化系统内存环境;显示的声明数组空间,而且申请数量还极大。

这是一个案例想定供大家警戒

使用jspsmartUpload作文件上传,运行过程中经常出现java.outofMemoryError的错误,

检查之后发现问题:组件里的代码

m_totalBytes = m_request.getContentLength();

m_binArray = new byte[m_totalBytes];

问题原因是totalBytes这个变量得到的数极大,导致该数组分配了很多内存空间,而且该数组不能及时释放。解决办法只能换一种更合适的办法,至少是不会引发outofMemoryError的方式解决。参考:http://bbs.xml.org.cn/blog/more.asp?name=hongrui&id=3747

5、尽量运用对象池技术以提高系统性能;生命周期长的对象拥有生命周期短的对象时容易引发内存泄漏,例如大集合对象拥有大数据量的业务对象的时候,可以考虑分块进行处理,然后解决一块释放一块的策略。

6、不要在经常调用的方法中创建对象,尤其是忌讳在循环中创建对象。可以适当的使用hashtable,vector 创建一组对象容器,然后从容器中去取那些对象,而不用每次new之后又丢弃

7、一般都是发生在开启大型文件或跟数据库一次拿了太多的数据,造成 Out Of Memory Error 的状况,这时就大概要计算一下数据量的最大值是多少,并且设定所需最小及最大的内存空间值。 

原创粉丝点击