赞
踩
jdk包含jre,jre包含jvm
1. Sun Classic VM - 第一款商用Java虚拟机 - 只能使用解释器方式执行java 2. Exact VM - 编译器和解释器混合执行,两级即时编译器 - 只在Solaris平台发布,就被取代了 3. HotSpot VM - 称霸武林 - 非sun开发,后收购的 4. KVM - 手机平台运行 5. JRockit - BEA公司 - 专注服务器端 6. J9 -IBM 7. Microsoft JVM
生命周期随着线程的创建而创建,随着线程的结束而死亡;所以不用关心这部分的垃圾回收。
① 程序计数器
②虚拟机栈
注意:人们常说,Java的内存空间分为“栈”和“堆”,栈中存放局部变量,堆中存放对象。
这句话不完全正确!这里的“堆”可以这么理解,但这里的“栈”只代表了Java虚拟机栈中的局部变量表部分。真正的Java虚拟机栈是由一个个栈帧组成,而每个栈帧中都拥有:局部变量表、操作数栈、动态链接、方法出口信息。
③本地方法栈
④堆
⑤方法区
⑥ 直接内存(不属于虚拟机内存)
综上所述
内存溢出的具体可能情况:
三色标记法: 具体是,黑白灰,
黑色为已标记的,灰色是正标记的,白色为未标记的。
针对新生代: 通常复制算法
针对老年代: 标记-整理,标记清除。
(老年代对象一般较大不适合复制算法,浪费空间。标记-整理在可用对象多的情况下很适合。)
内存浪费的解决方案。新生代分为Eden,From Survivor,To Survivor,比例是8:1:1。我们认为垃圾回收后剩余大约10%的有用对象。在Eden的对象垃圾收集以后剩余的放在Survivor,From与To之间是复制算法的关系。当Survivor内存不够时就需要一个内存担保,Tenured Gen。放到老年代。
新生代 | 老年代 | 特点 |
---|---|---|
serial | serial old | stop the world(STW停顿时间) 、单线程 |
parallel scavenge | parallel old | 注重吞吐量; stop the world(STW停顿时间)、多线程并行 |
ParNew | CMS | 可预测的停顿时间; gc线程与业务线程并发执行;cms无法处理浮动垃圾(标为不是垃圾后又变成垃圾的场景) ParNew是为了配置cms,与ps po特性一致 |
G1 | G1 | 兼顾吞吐量和停顿时间 |
ZGC | ZGC |
(1)CMS优点
(2)CMS缺点
G1计划作为并发标记扫描收集器(CMS)的长期替代品。
打印垃圾收集信息: -verbose:gc -XX:+PrintGCDetails
指定大对象的大小: -XX:PretenureSizeThreshold=8M
新生代通常是复制算法,新生代垃圾回收的频率很高,所以放在老年代更好。
指定年龄多少算长期 -XX:MaxTenuringThreshold 15
年龄计数器,每次垃圾回收年龄+1
内存不够时借用老年代内存
需要检查老年代是否有足够的空间容纳全部的新生代
开启空间分配担保 -XX:+HandlePromotionFailure
禁用空间分配担保 -XX:-HandlePromotionFailure
逃逸分析:分析对象的作用域。
栈上分配是java虚拟机提供的一种优化技术,在栈上申请空间,而栈是函数运行完立即清理,所以不需要等到gc,大大缓解了gc的压力。
没有发生逃逸的对象放在栈内存中。
public class PartionOnStack { static class User{ private int id; private String name; public User(){} } private static User user; public static void foo() { user=new User(); user.id=1; user.name="sixtrees"; } public static void main(String[] args) { foo(); } }
因为上面的代码中的User的作用域是整个Main Class,所以user对象是可以逃逸出函数体的。下面的代码展示的则是一个不能逃逸的代码段。
public class PartionOnStack { class User{ private int id; private String name; public User(){} } public void foo() { User user=new User(); user.id=1; user.name="sixtrees"; } public static void main(String[] args) { PartionOnStack pos=new PartionOnStack(); pos.foo(); } }
- Jps - Java process status - 控制台 打 "jps". 显示Java进程id - jps -l 运行时主类全名或jar包名 - jps -m 运行时主类接收的参数(在args中) - jps -v 接收的VM的参数 - 本地虚拟机唯一Id lvmid local virtual machine id - Jstat - 依赖jps, 需要知道进程的id才能使用 - 官网可查看文档 - jstat -gcutil {id} 垃圾回收概要信息 - Jinfo - 实时查看和调整虚拟机的各项参数 - jinfo -flag UseSerialGC {id} 查看该进程是否使用SerialGC。是(+),否(-) - Jmap - jmap -dump:format=b,file=/Users/yuan/a.bin {进程id} 转储快照 - jmap -histo {id} 类和实例信息 - Jhat - 分析Jmap快照 - jhat {文件路径} - 启动http server - Jstack - 线程快照 - Jstack {id} - JConsole - 内存监控 - 线程监控 - 死锁检测 - VisualVM 需下载
解决:
部署多个web容器,每个web容器堆内存设置为4G.用nginx负载。 这样解决了堆内存多大垃圾收集时间长。又不浪费内存。
总结:
没有大对象,不经常Full GC,部署多个容器更好。否则单个容器分配大的内存更好。毕竟容器启动会有额外内存,硬盘开销。
环境
jdk5, 2G内存, intel core i3, win server
问题
不定期内存溢出,堆内存加大也无济于事,导出堆快照,没人信息。内存监控,正常
处理思路
捕获到了bytebuffer。系统用了很多NIO。direct memory改大一些。
JVM崩溃。 Connect Reset
任务挤压,大量未处理任务导致
解决:加消息队列
三个过程:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。