JVM(二)—— 垃圾回收
一、内存分配
1.1 JVM 内存结构
Java 虚拟机的内存空间分为 5 个部分:
- 程序计数器
- Java 虚拟机栈
- 本地方法栈
- 堆
- 方法区
程序计数器(PC)
为什么需要程序计数器
因为Java虚拟机的多线程是通过线程轮流切换
并分配处理器执行时间
的方式来实现的。任意时刻,一个处理器只执行一条指令,为了进程切换后恢复到正确的执行位置,所以才有了程序计数器
作用
记录当前线程的执行字节码的位置,线程私有,也就是每个线程都有一个单独的计数器来记录。
特点
- 不会发生OutOfMemoryError
- 执行Native方法,计数器值为空
- 线程私有
Java虚拟机栈
描述Java方法执行的内存模型。
方法在执行的时候会创建一个栈帧,方法的调用到完成,对应着栈帧
在虚拟机栈中入栈
到出栈
的过程。
一个线程的方法调用可能很长,很多方法都处于执行状态。对于执行引擎来说,只有处于栈顶的栈帧(当前栈帧
)才有效,与之相关联的方法是当前方法
。
栈帧用于存储局部变量表
、操作数栈
、动态链接
、方法出口
等信息。
局部变量表
局部变量表存放编译期可知的基本数据类型
、对象引用
和return Address类型
局部变量表所需要的内存空间在编译期间完成分配。
特点
- 线程私有
- 线程请求的栈深度大于JVM允许深度,抛出
StackOverflowError
异常 - 虚拟机栈动态扩展时,无法申请足够的内存,抛出
OutOfMemoryError
异常
本地方法栈
堆
用来存放对象的内存空间,几乎所有的对象都存储在堆中。
堆的特点
- 线程共享
- 垃圾回收的主要场所
方法区
方法区的定义
运行时常量池
二、垃圾回收
垃圾回收主要解决三个问题(回收哪些Which,什么时候回收WHEN,如何回收HOW)
一、回收哪些
这三个问题,最主要的还是第一个,Which回收哪些,评断回收还是不回收的标准是看对象是否被引用
引用分为四种:
- 强引用:一个对象被一个引用所指向。绝对不会被JVM回收的,即使内存不过用
- 软引用:只有在堆内存不够用的时候才会被回收。使用SoftReference实现
- 弱引用:弱引用相对于软引用,引用级别更低。只要垃圾回收器启动了回收,就会被回收掉。绝WeakReference实现
- 虚引用:虚引用的主要作用是跟踪对象被垃圾回收的状态。虚引用对对象本身没有太大影响,必须和引用队列(ReferenceQueue)联合使用
1、引用计数法
如果两个对象相互引用,就不会被回收,当然,GC并没有采用这种算法
2、根搜索算法
从根开始,沿着整个对象图上的每条链接,确定可达的对象,如果对象不可达,则作为垃圾收集
是对(1)的改进,根对象到达某一对象不可达,GC就会对其回收。
public static void main(String[] args) {
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
n1.next = n2;
n3 = n2;
n2 = null;
}
二、何时回收,如何回收
这就需要垃圾收集算法来解决,但讲垃圾回收算法之前需要明白一个分代的概念
1、分代的策略
绝大多数的对象不会被长时间引用,这些对象在其Young期间就会被回收
很老的对象和很新的对象之间很少存在相互引用
Young代
大部分垃圾回收器对Young代都采用复制算法,为什么?因为Young代处于可达的对象数量少,所以复制成本不大
Young代由一个Eden区和2个Survivor区构成。绝大多数对象先分配到Eden区中,Survivor区中的对象都至少经历过一次垃圾回收
为什么要有2个Survivor区,是因为其中一个Survivor是空的,来存放Young代的对象。最后会清空Eden区和第一个Survivor区
思考:Survivor的大小设置的变化会产生什么影响
Old代
Young代的对象经过多次垃圾回收依然没有被回收,就会被转移到Old代
随着时间流逝,Old代的对象会越来越多,因此Old代的空间要与Young代的空间大
Old代的垃圾回收的两个特征:Old代垃圾回收的执行频率不需要太高,因为死的少。每次回收需要更长的时间来完成(如何理解,因为对象多吧)
垃圾回收通常会采用标记压缩算法。因为对象不会很快死亡,也不会大量产生内存碎片
Permanent代
主要用于装载Class、方法等信息
垃圾回收机制通常不会回收这一代的对象。
服务器程序通常会加载很多类,需要加大Permanent代内存。
OutOfMemoryError:PermGen space错误
2、垃圾回收算法
标记-清除算法
标记所有需要回收的对象,标记完成后,统一回收所有被标记的对象,
不足之处,标记和清除的效率不高,标记清除后会产生大量不连续的内存碎片
复制算法
为了解决效率问题,将内存分为大小相等的两块,每次使用一块,当这一块内存使用完了之后,将存活的对象放到另一块内存中,然后对原先那一半内存进行回收。实现简单,运行高效,不过代价是将内存缩小一半,代价过高。
标记-整理算法
是对标记清除算法的改进,进行标记好了之后,将存活的对象都向一边移动,然后直接清理掉端边界以外的内存
分代收集算法
商业虚拟机都采用“分代收集”算法,根据对象的存活周期将内存分为几块,一般是将java堆分成新生代和老年代,如果新生代有很少的存活对象,就用复制算法,老年代有很多存活对象,就用标记-清除或标记-整理算法
HotSpot虚拟机下的垃圾收集器
由于内存中的对象,是按存活周期存放在不同的内存块中的,所以,我们选择不同的算法来针对不同的内存块进行垃圾收集。从而,对于,不同的内存块,我们需要有不同的垃圾收集器。
新生代的垃圾收集器有:Serial收集器
、ParNew收集器
、Parallel Scavenge收集器
老年代的垃圾收集器有:Serial Old收集器
、Parallel Old收集器
、CMS收集器
、G1收集器
Serial收集器/Serial Old收集器
串行,是单线程的,使用“复制”算法。当它工作时,必须暂停其它所有工作线程
。特点:简单而高效。一般用于Client模式的JVM中
Serial Old是老年代的单线程收集器,使用标记-整理算法。
ParNew收集器
ParNew收集器,是Serial收集器的多线程版。是运行在Server模式下的虚拟机中首选的新生代收集器。除了Serial收集器外,目前只有它能与CMS收集器配合工作。
Parallel Scavenge收集器
吞吐量优先收集器,吞吐量=程序运行时间/(JVM执行回收时间+程序运行时间),是server模式JVM的默认配置
Parallel Old收集器
老年代的多线程收集器,使用标记-整理算法,吞吐量优先,适合于Parallel Scavenge搭配使用
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,使用“标记-清除”算法。
回收线程数=(CPU核心数+3)/4
CMS收集器分4个步骤进行垃圾收集工作:
1、初始标记 2、并发标记 3、重新标记 4、并发清除
其中“初始标记”、“重新标记”是需要暂停其它所有工作线程的。
G1收集器
G1(Garbage First)收集器,基于“标记-整理”算法,可以非常精确地控制停顿。
可以不与其他收集器搭配,独立收集新生代和老年代。
三、内存管理技巧
1、尽量使用直接量:String str = "hello"
2、使用StringBuilder和StringBuffer进行字符串连接
3、尽早释放无用对象的引用
Object obj = new Object();obj = null;这行代码并不能发挥C++中的delete和free作用,其作用仅仅是断开obj 与new Object()的关联,new Object所占用的内存并没有释放掉。以此来诱发GC对其进行回收。如果是在方法中,其实要考虑两种情况,多数情况下不需要这么写,对象会随着因为方法调用的结束而结束。但如果obj =null之后,还有耗时耗内存的操作的话,就需要这样写。
四、设置Java虚拟机内存的一些参数
- -Xmx 设置堆内存的最大容量
- -Xms 设置堆内训初始容量
- -XX:NewSize = size 设置Young代内存的默认容量
- -XX:SurvivorRatio = 8 设置Young代中eden/survivor的比例
- -XX:MaxNewSize = size 设置Young代内存的最大容量
- -XX:PermSize = size 设置永久代的默认容量
- -XX:MaxPermSize = size 设置永久代内存的最大容量
五、一次完整的GC流程
从ygc到fgc
六、监控工具
jstat
jstat -gc 14122 250 20
jstat -gcutil 14122 250 20
一、Class结构
dir
参考文档
[1]: JVM 解剖公园(19): 锁省略
[2]: Java性能调优实战视频全集
JVM(二)—— 垃圾回收的更多相关文章
- JVM总括二-垃圾回收:GC Roots、回收算法、回收器
JVM总括二-垃圾回收:GC Roots.回收算法.回收器 目录:JVM总括:目录 一.判断对象是否存活 为了判断对象是否存活引入GC Roots,如果一个对象与GC Roots没有直接或间接的引用关 ...
- jvm的垃圾回收算法
一.对象存活判断判断对象是否存活一般有两种方式:1.引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收.此方法简单,无法解决对象相互循环引用的问题.2 ...
- JVM的垃圾回收机制 总结(垃圾收集、回收算法、垃圾回收器)
相信和小编一样的程序猿们在日常工作或面试当中经常会遇到JVM的垃圾回收问题,有没有在夜深人静的时候详细捋一捋JVM垃圾回收机制中的知识点呢?没时间捋也没关系,因为小编接下来会给你捋一捋. 一. 技术 ...
- 扒一扒JVM的垃圾回收机制,下次面试你准备好了吗
相信和小编一样的程序猿们在日常工作或面试当中经常会遇到JVM的垃圾回收问题,有没有在夜深人静的时候详细捋一捋JVM垃圾回收机制中的知识点呢?没时间捋也没关系,因为小编接下来会给你捋一捋. 一. 技 ...
- JVM的垃圾回收机制
JVM的垃圾回收机制:(GC通过确定对象是否被活动对象引用来确定是否收集该对象.) 1.触发GC(Garbage Collector)的条件. (1.GC在优先级最低的线程中运行,在未运行的线程中进行 ...
- 2.1.JVM的垃圾回收机制,判断对象是否死亡
因为热爱,所以坚持. 文章下方有本文参考电子书和视频的下载地址哦~ 这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么.然后触发条件是什么.最后虚拟机如何判断对象是否死亡. 一.前言 我们 ...
- JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析 !
因为热爱,所以坚持. 文章下方有本文参考电子书和视频的下载地址哦~ 这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么.然后触发条件是什么.最后虚拟机如何判断对象是否死亡. 一.前言 我们 ...
- JVM虚拟机垃圾回收(GC)算法及优缺点
一.什么是GC GC是jvm的垃圾回收,垃圾回收的规律和原则为: 次数上频繁收集新生区(Young) 次数上较少收集养老区(Old) 基本上不动永久区(Perm) 二.GC算法(分代收 ...
- JVM学习——垃圾回收GC(学习过程)
JVM学习-垃圾回收(GC) 2020年02月19日06:03:56,开始学习垃圾回收,学习资料来源(张龙老师的JVM课程) JVM内存数据区域知识复习 学习垃圾回收之前,要对JVM内部的内存区域有详 ...
- JVM的垃圾回收机制详解和调优
JVM的垃圾回收机制详解和调优 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都 ...
随机推荐
- volatile的使用
//资源(把 volatile去掉进行测试 )public class Demo { volatile int i =1;}//测试 public static void main(String[] ...
- Python Moment.js api
moment.js(js date)日期格式化处理插件强大,官方网站:http://momentjs.com/你也可以查看官方网站E文原版moment.js api.当前日期格式化 moment(). ...
- Connect To Ubuntu 16.04 / 17.10 / 18.04 Desktop Via Remote Desktop Connection (RDP) With Xrdp
[1] https://websiteforstudents.com/connect-to-ubuntu-16-04-17-10-18-04-desktop-via-remote-desktop-co ...
- Appium日志乱码终结指北
缘起 最近Android,IOS自动化多开群控都搞好了,但是Appium中的log 显示中文乱码问题像个苍蝇一样,看着感觉特别难受,挥之不去,抚之不平.论坛搜索了一下,很多帖子都反映过这个问题,但是都 ...
- entity.Database.SqlQuery() 和entity.Database.SqlCommand()
原文地址: http://msdn.microsoft.com/en-us/library/gg715124(v=vs.103) 使用 EF 4.1 或者更新版本, 你可以直接执行任何数据库命令. 在 ...
- Java编程实现多线程TCP服务器完整实例
Socket ·功能:TCP客户端套接字 ·构造方法: Socket(InetAddress address, int port) 创建一个流套接字并将其连接到指定 IP 地址的指定端口号 · ...
- 5.AutoCompleteTextView、自定义广播
新建信息 布局:自动出来的是系统的组件,里面是listview,写ontextchanglis也行 <LinearLayout xmlns:android="http://schema ...
- H5中用js让页面全屏
概述 意外的发现一个网页有一个按钮能使网页全屏,查了下代码发现是H5的全屏api,于是就查了下资料,记录下来供以后开发时参考,相信对其他人也有用. 参考资料: 利用js如何做到让页面全屏和不全屏功能 ...
- 一个简单的实例演示vuex模块化和命名空间
因为Vuex Store是全局注册的,不利于较大的项目,引入模块分离业务状态和方法,引入命名空间解决不同模块内(getters,mutaions,actions)名称冲突的问题 ----------- ...
- GNU 下命令objcopy 用法
概念: 将目标文件的一部分或者全部内容拷贝到另外一个目标文件中,或者实现目标文件的格式转换. 常用转换: 1 把elf格式转成s19格式: objcopy --srec-len --srec-forc ...