Java虚拟机的内存管理
众所周知,Java程序员写的代码是没有办法控制Java对象的内存释放的,完全有JVM暗箱操作.
虽然程序员把内存的释放的任务都交给了Java虚拟机,但是并不代表Java程序就不存在内存泄漏.
反而,某程度上,当出现内存泄漏,Debug会变得难度更大.
所以,Java程序员,有必要去了解Java虚拟机对于内存的管理以及垃圾回收的机制.
Java虚拟机是如何判断一个对象可以回收?
当一个对象没有被任何其他所引用时,这个对象被Java虚拟机视为可回收.
早起的虚拟机,使用引用计数的方法判断对象是否可回收.这个方法的好处是简单和效率高,却难以解决循环引用的问题.
现在主流的Java虚拟机都是使用可达性的分析对象是否可回收.从若干Root节点开始遍历,所有从Root节点能到达的对象,都是存活对象.
反之,其他对象就是可回收对象.可以想象,这是有若干个根节点的图,用图论术语就是判断每个节点的可达性.
强引用,软引用,弱引用,虚引用都是什么?
强引用Strong Reference就是平时最常见的,不加任何修饰的对象实例化,得到的都是强引用.
软引用Soft Reference,软引用的对象,当Java虚拟机垃圾回收时出现空间不足的情况,软引用的对象就会被回收.
弱引用Weak Reference,弱引用的对象,当Java虚拟机下一次垃圾回收时,无论如何都会被回收.
虚引用Phantom Reference,虚引用的对象任何一个时刻都不能取得其对象的实例.虚引用的使用在于跟踪对象的生死存亡,当虚引用被垃圾回收时,会收到一个系统通知.
垃圾回收算法都有哪些?
1.标记清除,顾名思义就是标记和清除两个阶段.这个算法的致命弱点是,会产生大量的内存碎片,导致后期即使有足够的内存空间也无法分配大的连续的内存空间.
2.复制算法,是把内存空间分成大小相等的两个区域,每次只使用其中一个区域.每次内存回收,都会把存活的对象复制到另外一个区域.
这个算法虽然解决了内存碎片的问题,但是是以内存缩小原来的一半为代价.
复制算法也常用在新生代的垃圾回收.因为大多数的对象都是朝生夕死的,不会存活过下一轮的垃圾回收.所以实际上并没有必要按照1:1的比例来划分内存空间.
现实情况,内存被划分为一个较大的eden区和两个较小的survivor区.HotSpot虚拟机的eden:survivor:survivor=8:1:1.
每次都会使用eden和其中一个survivor用来分配内存,当垃圾回收时会把存活的对象复制到另外一个survivor区.
当出现survivor的内存不足时,会动用老年代的内存空间.老年代起的是一个担保的作用.
3.标记整理算法.把存活的对象都标记出来,再移动到内存空间的一端,把端边界以外的内存空间都清除释放.老年代一般采用标记整理算法.
4.分代收集算法.一般把内存空间分成老年代和新生代,不同的区域根据对象存活的周期和特点,使用合适的垃圾回收算法.
新生代使用复制算法.老年代使用标记清除或者标记整理算法.
Java程序会在什么时候执行垃圾回收呢?
答案是,安全区域(Safe Region),指在一端代码片段之中,引用关系不会发生变化,在这个区域任意地方开始垃圾回收都是安全的.
当线程执行到安全区域时,会首先标识自己已经进入了安全区域.
当线程要离开安全区域时,它要检查系统是否已经完成了根节点枚举(或整个垃圾回收过程),如果完成那线程就继续执行,否则必须等到可以离开安全区域的信号为止.
让所有执行线程都停顿下来到达最近的安全区域,有两种方案:
1.抢占式中断(Preemptive Suspension).在垃圾回收发生时,首先把所有线程都全部中断,没有到达安全区域的线程,就恢复线程让它运行到最近的安全区域上.
现在,几乎没有Java虚拟机是使用抢占式中断,来暂停所有线程从而执行垃圾回收.
2.主动式中断(Voluntary Suspension).当准备执行垃圾回收时,会设置一个标志位,表示要开始垃圾回收了.所有线程都会在安全区域处轮询这个标志位.
当发现这个标志位被设置后,线程会暂停自己.
Java虚拟机的内存管理的更多相关文章
- 深入java虚拟机学习 -- 内存管理机制
前面说过了类的加载机制,里面讲到了类的初始化中时用到了一部分内存管理的知识,这里让我们来看下Java虚拟机是如何管理内存的. 先让我们来看张图 有些文章中对线程隔离区还称之为线程独占区,其实是一个意思 ...
- java虚拟机(一)——内存管理机制与OOM异常
一 java内存区域与内存溢出异常(OOM) 1)运行时数据区域划分 1.程序计数器(Program Conuter Register) 程序计数器是一块较小的内存空间,它是当前线程执 ...
- 深入了解Java虚拟机和内存管理
1.java程序的执行过程 java源文件->解析器->class文件->java类加载器->java运行时数据区->执行引擎 2.我们接下来看一下java运行 ...
- [深入理解Java虚拟机]<自动内存管理>
Overview 走近Java:介绍Java发展史 第二部分:自动内存管理机制 程序员把内存控制的权利交给了Java虚拟机,从而可以在编码时享受自动内存管理.但另一方面一旦出现内存泄漏和溢出等问题,就 ...
- 深入理解JAVA虚拟机 自动内存管理机制
运行时数据区域 其中右侧三个一起的部分是每个线程一份,左侧两个是所有线程共享的. 程序计数器(Program Counter Register) 英文名称叫Program Counter Regist ...
- Java虚拟机理解-内存管理
运行时数据区域 jdk 1.8之前与之后的内存模型有差异,方法区有变化(https://cloud.tencent.com/developer/article/1470519). java的内存数据区 ...
- 深入理解java虚拟机,内存管理部分
1,对象回收前会调用finalize()方法,尝试自救,只能调用一次 2,上面横向对比c++的析构函数,但是java有良好的内存管理,而且try/catch做得比较好 3,回收一个常量,1,对象的实例 ...
- Java虚拟机的内存管理----垃圾收集器
1.Serial收集器 优点,是简单而高效,单线程避免了线程交互的开销. 缺点,进行垃圾回收时需要Stop the world(暂停所有用户线程). 2.ParNew收集器 它是Serial收集器的多 ...
- Java虚拟机之内存区域
原创文章,转载请标明出处! 目录 一.背景 二.运行时内存区域概述 1.官方描述 2.中文翻译 3.内存区域简述 4.运行时数据区简图 5.运行时数据区详图 三.JVM线程 JVM数据区域与线程关系 ...
随机推荐
- 实现Django ORM admin view中model字段choices取值自动更新的一种方法
有两个表,一个是记录网站信息的site表,结构如下: CREATE TABLE `site` ( `id` ) unsigned NOT NULL AUTO_INCREMENT, `name` ) N ...
- day 3 局部变量 全局变量
1.局部变量 2.全局变量(死歌的大招)函数前面声明的都是全局变量 3.全局变量和局部变量的区别 1)老方法 def get_temper(): temper = 33 return temper d ...
- Android 自动化测试及性能数据采集的 Python 脚本
文主要介绍一个基于 uiautomator2 封装的一个 Python 库 android-catcher ,该库的功能主要有对 Android 设备进行 UI 自动化测试 和 采集手机性能数据 ,适 ...
- Django-建立网页
进入cmd模式做 django-admin startproject helloworld创建一个project,并命名helloworld,新生成的文件结构如下 输入python manage. ...
- 面向英特尔® x86 平台的 Unity* 优化指南: 第 1 部分
原文地址 目录 工具 Unity 分析器 GPA 系统分析器 GPA 帧分析器 如要充分发挥 x86 平台的作用,您可以在项目中进行多种性能优化,以最大限度地提升性能. 在本指南中,我们将展示 Uni ...
- 《Angular4从入门到实战》学习笔记
<Angular4从入门到实战>学习笔记 腾讯课堂:米斯特吴 视频讲座 二〇一九年二月十三日星期三14时14分 What Is Angular?(简介) 前端最流行的主流JavaScrip ...
- File Transfer(并查集)
题目大意:将多个电脑通过网线连接起来,不断查询2台电脑之间是否连通. 问题来源:中国大学mooc 05-树8 File Transfer (25 分) We have a network of com ...
- EasyUI tree 优化--点击文字折叠展开效果
$(function () { $('#tree_menu').tree({ onSelect: function (node) { if (node.state == "closed&qu ...
- fail-fast 机制 思考
HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的. Iterator支持fail-fast机制,而Enum ...
- NodeJS实现同步的方法
NodeJS被打上了单线程.非阻塞.事件驱动…..等标签. 在单线程的情况下,是无法开启子线程的.经过了很久的研究,发现并没有thread函数!!!但是有时候,我们确实需要“多线程”处理事务.node ...