- 浏览: 94477 次
- 性别:
- 来自: 深圳
文章分类
最新评论
3.2 JVM内存管理
Java不需要开发人员来显式分配内存和回收内存,而是由JVM来自动管理内存的分配及回收(又称为垃圾回收、Garbage Collection或GC),这对开发人员来说确实大大降低了编写程序的难度,但副作用可能是在不知不觉中浪费了很多内存,导致JVM花费很多时间进行 内存的回收。另外还可能会带来的副作用是由于不清楚JVM内存的分配和回收机制,造成内存泄露,最终导致JVM内存不够用。因此对于Java开发人员而 言,不能因为JVM自动内存管理就不掌握内存分配和回收的知识了。
除了内存的分配及回收外,还须掌握跟踪分析JVM内存的使用状况,以便更加准确地判断程序的运行状况及进行性能的调优。
3.2.1 内存空间
Sun JDK在实现时遵照JVM规范,将内存空间划分为方法区、堆、本地方法栈、PC寄存器及JVM方法栈,如图3.7所示。
图3.7 JVM内存结构 |
方法区
方法区存放了要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当开 发人员在程序中通过Class对象的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域。方法区域也是全局共享的,在 一定条件下它也会被GC,当方法区域要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
在Sun JDK中这块区域对应Permanet Generation,又称为持久代,默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来指定最小值和最大值。
堆
堆用于存储对象实例及数组值,可以认为Java中所有通过new创建的对象的内存都在此分配,Heap中对象所占用的内存由GC进行回收,在32位 操作系统上最大为2GB,在64位操作系统上则没有限制,其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为 物理内存的1/64但小于1GB;-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB,默认当空余堆内存小于40% 时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRatio=来指定这个比例;当空余堆内存大于70%时,JVM会 减小Heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRatio=来指定这个比例,对于运行系统而言,为避免在运行时频繁调整 Heap 的大小,通常将-Xms和-Xmx的值设成一样。
为了让内存回收更加高效,Sun JDK从1.2开始对堆采用了分代管理的方式,如图3.8所示。
图3.8 Sun JDK堆的分代 |
1. 新生代(New Generation)
大多数情况下Java程序中新建的对象都从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(通常又称为S0和S1或From和To)构成,可通过-Xmn参数来指定新生代的大小,也可通过-XX:SurvivorRatio来调整 Eden Space及Survivor Space的大小。不同的GC方式会以不同的方式按此值来划分Eden Space和Survivor Space,有些GC方式还会根据运行状况来动态调整Eden、S0、S1的大小。
2. 旧生代(Old Generation或Tenuring Generation)
用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象,新建的对象也有可能在旧生代上直接分配内存。主要有两种状况(由不同的GC实现来 决定):一种为大对象,可通过在启动参数上设置-XX:PretenureSizeThreshold=1024(单位为字节,默认值为0)来代表当对象 超过多大时就不在新生代分配,而是直接在旧生代分配,此参数在新生代采用Parallel Scavenge GC时无效,Parallel Scavenge GC会根据运行状况决定什么对象直接在旧生代上分配内存;另一种为大的数组对象,且数组中无引用外部对象。
旧生代所占用的内存大小为-Xmx对应的值减去-Xmn对应的值。
本地方法栈
本地方法栈用于支持native方法的执行,存储了每个native方法调用的状态,在Sun JDK的实现中本地方法栈和JVM方法栈是同一个。
PC寄存器和JVM方法栈
每个线程均会创建PC寄存器和JVM方法栈, PC寄存器占用的可能为CPU寄存器或操作系统内存,JVM方法栈占用的为操作系统内存,JVM方法栈为线程私有,其在内存分配上非常高效。当方法运行完毕时,其对应的栈帧所占用的内存也会自动释放。
当JVM方法栈空间不足时,会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定其大小,例如如下代码:
new Thread(new Runnable(){
public void run() {
loop(0);
}
private void loop (int i){
if(i!=1000){
i++;
loop (i);
}
else{
return;
}
}
}).start();
当JVM参数设置为-Xss1K时,运行后报出类似下面的错误:
Exception in thread "Thread-0" java.lang.StackOverflowError
Java对象所占用的内存主要从堆上进行分配,堆是所有线程共享的,因此在堆上分配内存时需要进行加锁,这导致了创建对象开销比较大。当堆上空间不足时,会触发GC,如果GC后空间仍然不足,则抛出OutOfMemory错误信息。
Sun JDK为了提升内存分配的效率,会为每个新创建的线程在新生代的Eden Space上分配一块独立的空间,这块空间称为TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行情况计算而得,可通过-XX:TLABWasteTargetPercent来设置TLAB可占用的Eden Space的百分比,默认值为1%。JVM将根据这个比率、线程数量及线程是否频繁分配对象来给每个线程分配合适大小的TLAB空间 。在TLAB上分配内存时不需要加锁,因此JVM在给线程中的对象分配内存时会尽量在TLAB上分配,如果对象过大或TLAB空间已用完,则仍然在堆上进 行分配。因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效,可通过在启动参数上增加-XX:+PrintTLAB来查看TLAB空 间的使用情况 。
在分配细节上取决于GC的实现,后续GC的实现章节会继续介绍。
除了从堆上分配及从TLAB上分配外,还有一种是基于逃逸分析直接在栈上进行分配的方式,此方式已在前文中提及。
发表评论
-
技术文章精华合集(持续更新中)
2016-09-20 19:09 712Kafka深度解析 分库分表系列文章 来自 ... -
<<More Joel on Software>> 如何扮演程序经理的角色
2011-07-03 15:13 796制作伟大软体的秘方之 ... -
<<More Joel on Software>> 利诱管理法
2011-07-03 15:10 957利诱管理法 Joke: A poor J ... -
<<More Joel on Software>> The Joel Test: 软件开发成功 12 法则
2011-07-03 14:42 688作者: 周思博 (Joel Spols ... -
<<More Joel on Software>> 看起来简单, 实际上复杂
2011-07-03 14:41 760作者: 周思博 (Joel Spolsky) 译: Bo Y ... -
<<More Joel on Software>> 膨胀软件与80/20的谣传
2011-07-03 14:38 885作者: 周思博 (Joel Spols ... -
<<More Joel on Software>> 每日构建(daily build)是你的朋友
2011-07-03 14:37 849作者: 周思博 (Joel Spols ... -
<<More Joel on Software>> 五个为什么
2011-07-03 14:20 954五个为什么(译文) ... -
<<More Joel on Software>> 飙高音
2011-07-03 13:54 905飙高音(译文) 作者: 阮一峰 日期: 2009年 ... -
<<More Joel on Software>> 关于战略问题的通信之六
2011-07-03 13:51 768关于战略问题的通信之六(译文) 作者: 阮一峰 日 ... -
<<More Joel on Software>> 易用性是不够的
2011-07-03 13:41 738易用性是不够的(译文) 作者: 阮一峰 日期: 2 ... -
<<More Joel on Software>> 军事化管理法
2011-07-03 13:28 961高科技公司能否采用军事化管理?(译文) 作者: 阮一峰 ... -
<<More Joel on Software>> 寻找优秀的程序员
2011-07-03 13:24 1194=================== 寻找 ... -
读书笔记:《分布式JAVA应用 基础与实践》 第七章 构建可伸缩的系统
2011-05-29 12:09 1103通常将通过升级或增加单机机器的硬件来支撑访问量及数据量增长的方 ... -
读书笔记:《分布式JAVA应用 基础与实践》 第六章 构建高可用的系统
2011-05-28 11:02 1197对于互联网或企业中的大型应用而言,多数要求做到 7*24 ... -
读书笔记:《分布式JAVA应用 基础与实践》 第五章 性能调优(二)
2011-05-22 21:34 10885.2 调优 找出性 ... -
读书笔记:《分布式JAVA应用 基础与实践》 第五章 性能调优(一)
2011-05-22 13:43 11335.1 寻找性能瓶颈 通常性能瓶颈的 ... -
读书笔记:《分布式JAVA应用 基础与实践》 第四章 分布式JAVA应用与JDK类库
2011-05-21 11:23 11754.1 集合包 ArrayList, Li ... -
读书笔记:《分布式JAVA应用 基础与实践》 第三章 3.3 JVM线程资源同步及交互机制(二)
2011-05-17 21:52 936接下来网上没有,貌似 ... -
《分布式JAVA应用 基础与实践》 第三章 3.3 JVM线程资源同步及交互机制(一)
2011-05-17 19:09 8873.3 JVM线程资源同步及交互机制 Java程序采用 ...
相关推荐
Java分布式应用学习笔记02再谈JVM
JVM 内存管理之道 JVM垃圾回收机制 JVM GC组合 JVM 内存监控工具
java获得jvm内存大小
本书章节包括分布式java应用,大型分布式java应用与SOA,深入理解jvm,分布式应用与sun jdk类库,性能调优,构件高可用的系统等,同时也适合面试考察的知识点。
Sun JVM原理与内存管理
详细介绍了JVM 内存管理相关知识 内存空间( VM运行时数据区域) ◦ 内存结构 ◦ 内存空间 内存分配 内存回收(GC) 内存分析工具
Java分布式应用学习笔记-谈JVM
对于深入掌握的java的人士,对于内存管理是不得不看的东西
主要是JVM内存分配及简单的JVM性能调优
分布式移动开发总结:对Java来说,这些子系统可能部署在同一台机器的多个不同的JVM中,也可能部署在不同的机器上, 但这些子系统又不是完全独立的,要相互通信来共同实现业务功能。
(二)MATJVM 内存分析工具.MAT JVM 内存分析工具.MAT JVM 内存分析工具.(二)MATJVM 内存分析工具.MAT JVM 内存分析工具.MAT JVM 内存分析工具.
sun公司出版的jvm运行机制管理丛书,需要深入jvm的同学可以下载来看看
性能测试,线程的 dump 看到线程的 死锁,等待 运行状态
Java分布式应用学习笔记03JVM对线程的资源同步和交互机制
关于java的内存分配问题,jvm的运行原理相关资料总结
1. JVM调优 1.1 JVM调优总结(一)-一些概念 1.2 JVM调优总结(二)-一些概念 1.3 JVM调优总结(三)-基本垃圾回收算法 1.4 JVM调优总结(四)-垃圾...4.2 JVM内存管理:深入垃圾收集器与内存分配策略 4.3 深入理解JVM
jvm内存反洗工具:
第三节:定位垃圾对象的依据 1.1 引用计数法 1.2 可达性算法 第四节:垃圾回收算法 1.1标记清除算法 1.2复制算法 1.3 标记整理(标记压缩)算法 第五节:垃圾回收器 1.1Serial/Serial Old收集器 1.2 ParNew收集...
用java内存监控工具生成的JVM内存日志,用jmap生成的