堆和非堆内存
按照官方的说法:“Java 虚拟机具有一个堆(Heap),堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”“在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。
JVM主要管理两种类型的内存:堆和非堆。
Heap memory Code Cache
Eden Space
Survivor Space
Tenured Gen
non-heap memory Perm Gen
native heap?(I guess)
堆内存
Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。
堆的大小可以固定,也可以扩大和缩小。堆的内存不需要是连续空间。
非堆内存
Java 虚拟机管理堆之外的内存(称为非堆内存)。
Java 虚拟机具有一个由所有线程共享的方法区。方法区属于非堆内存。它存储每个类结构,如运行时常数池、字段和方法数据,以及方法和构造方法的代码。它是在 Java 虚拟机启动时创建的。
方法区在逻辑上属于堆,但 Java 虚拟机实现可以选择不对其进行回收或压缩。与堆类似,方法区的大小可以固定,也可以扩大和缩小。方法区的内存不需要是连续空间。
除了方法区外,Java 虚拟机实现可能需要用于内部处理或优化的内存,这种内存也是非堆内存。例如,JIT 编译器需要内存来存储从 Java 虚拟机代码转换而来的本机代码,从而获得高性能。
几个基本概念
PermGen space:全称是Permanent Generation space,即永久代。就是说是永久保存的区域,用于存放Class和Meta信息,Class在被Load的时候被放入该区域,GC(Garbage Collection)应该不会对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。
Heap space:存放Instance。
Java Heap分为3个区,Young即新生代,Old即老生代和Permanent。
Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。Permanent区则负责保存反射对象。
堆内存分配
- JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;
- JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。
- 默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;
- 空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。
- 因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。
- 说明:如果-Xmx 不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM,不是Throwable的,无法用try…catch捕捉。
非堆内存分配
- JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
- 由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
- 还有一说:MaxPermSize缺省值和-server -client选项相关,-server选项下默认MaxPermSize为64m,-client选项下默认MaxPermSize为32m。这个我没有实验。
- XX:MaxPermSize设置过小会导致java.lang.OutOfMemoryError: PermGen space 就是内存益出。
- 为什么会内存益出:
- 这一部分内存用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和存放Instance的Heap区域不同。
- GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS 的话,就很可能出现PermGen space错误。
- 这种错误常见在web服务器对JSP进行pre compile的时候。
JVM内存限制(最大值)
- 首先JVM内存限制于实际的最大物理内存,假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。
- 为什么有的机器我将-Xmx和-XX:MaxPermSize都设置为512M之后Eclipse可以启动,而有些机器无法启动?
通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统。所以说设置VM参数导致程序无法启动主要有以下几种原因:
- 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;
- -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。说到实际物理内存这里需要说明一点的是,如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。
- 如果你有一个双核的CPU,也许可以尝试这个参数: -XX:+UseParallelGC 让GC可以更快的执行。(只是JDK 5里对GC新增加的参数)
- 如果你的WEB APP下都用了大量的第三方jar,其大小超过了服务器jvm默认的大小,那么就会产生内存益出问题了。解决方法: 设置MaxPermSize大小。
- 增加服务器启动的JVM参数设置: -Xms128m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
- 如tomcat,修改TOMCAT_HOME/bin/catalina.sh,在echo “Using CATALINA_BASE: $CATALINA_BASE”上面加入以下行:JAVA_OPTS=”-server -XX:PermSize=64M -XX:MaxPermSize=128m
- 建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以减少jar 文档重复占用内存
JVM内存设置参数
- 内存设置参数
设置项 | 说明 |
---|---|
-Xms512m | 表示JVM初始分配的堆内存大小为512m(JVM Heap(堆内存)最小尺寸,初始分配) |
-Xmx1024m | JVM最大允许分配的堆内存大小为1024m,按需分配(JVM Heap(堆内存)最大允许的尺寸,按需分配) |
-XX:PermSize=512M | JVM初始分配的非堆内存 |
-XX:MaxPermSize=1024M | JVM最大允许分配的非堆内存,按需分配 |
-XX:NewSize/-XX:MaxNewSize | 定义YOUNG段的尺寸,NewSize为JVM启动时YOUNG的内存大小; |
MaxNewSize为最大可 |
首页 上一页 1 2 3 下一页 尾页 1/3/3 | |
【大 中 小】【打印】 【繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部】 | |
上一篇:高性能线程间队列 DISRUPTOR 简介 | 下一篇:聊聊 TCP 中的 KeepAlive 机制 |