Java JVM运行时数据区,内存管理和GC垃圾回收

一 . 运行时数据区
程序计数器是线程私有的,是一块很小的内存空间,是当前线程执行到字节码行号的计数指示器。每个CPU处理器核心 在任何一个时刻,都只可能运行着唯一的一个线程,执行着一条指令。所以在多线程的应用中,线程不断切换和分配时间片。在线程切换来切换去的过程中,就是靠程序计数器来了解,该如果继续恢复运行该线程。
虚拟机栈和Native方法栈也是线程私有的。在Sun HotSpot虚拟机中虚拟机栈和Native方法栈是被合二为一的。虚拟机栈描述的是Java方法执行的内存模型,栈帧用于存储局部变量表,方法出口等信息。每一个方法调用到执行完成都对应着一个栈帧在虚拟机栈中的入栈和出栈的过程。局部变量表中存放了八种基本数据类型和对象引用,还有returnAddress类型。前两种不难理解,returnAddress实际上是指向一条字节码指令的地址,局部变量表所需的内存空间在编译期间完成分配,当进入某个方法时,需要在栈帧中分配多大的局部空间是完全确定的,方法运行期间是不会改变局部变量表的大小。本地方法栈和虚拟机栈作用相似,虚拟机栈执行我们的java方法,本地方法栈就是执行Native方法,所以就是Native方法栈。简单地讲,一个Native Method就是一个java调用非java代码的接口。
Java堆是所有线程共享的区域,虚拟机管理的内存中最大的一块。基础所有对象的实例都是在这里分配内存。Java堆是GC的主要回收对象,虚拟机栈上局部变狼表所存的对象引用,就是指向堆内存中的一块地址。详细内容后面垃圾回收会提到更多。
方法区也是一块所有线程共享的区域,这里存储虚拟机加载的类信息,常量,静态变量,JIT编译后的代码等数据。运行时常量池是方法区的一部分。
接下来要说到JVM GC机制,在垃圾回收中堆内存上移动对象位置是很常见的, 所以对象的访问方式也要顺便提一下,也可以展示下方法区的类型是如何被引用的。我们都知道栈上的局部变量表中,有存储reference数据的引用,它可能是对象的直接地址,也可能是句柄地址。


由于对象访问极其频繁,所以Hot Spot也使用第二种方式,直接存实例引用是效率比较高的。但是第一种句柄的方式,好处在于,垃圾回收中,不需要更改栈上所存储的地址,栈上的存储稳定,只需要修改句柄池。
二.垃圾回收GC
说到垃圾回收 ,就不得不说垃圾回收算法的思想, 说到回收算法, 又不得不想到,什么样的对象需要被回收?什么是存活对象,什么对象已死亡。判断对象的存活与死亡,通常有两种方法,引用计数法和可达性分析算法。引用计数算法的问题在于,无法解决两个对象间相互引用的问题,导致不得达的对象依然无法回收。下面是实例:
A.b=B ; //这里 B 引用计数+1 A对象在堆上 其属性b存着B的引用
B.a=A ; // 与上方同理
A=null;
B=null; //A B两对象栈上引用 给null AB堆上实例做到不可达
//此时导致 AB对象实例内存不会被回收
所以为了解决这个问题,Java虚拟机中 使用可达性分析算法。其思想是从可作为GC Root根结点的对象,向下搜索,搜索过的路成为引用链,凡事不能达到的对象,认为是可回收对象。有几种对象可以作为GC Root对象。
1. 虚拟机栈上(栈帧的本地变量表)引用的对象。 2. 方法区中类静态属性引用的对象。 3. 方法区中常量引用的对象 4. 本地方法栈上Native方法引用的对象。
试想一下,为什么这些对象可以作为GC Root,为什么其他对象无法作为GC Root。 比如你的一个接口,处理请求的时候,有很多线程本地变量 , 但是 处理完请求后,这些对象就都没用了,所以他们一般不能作为GC Root。什么时候本地变量会成为GC Root呢? 个人的猜测应该是在GC大面积回收,程序暂停的时候, 这个时候,不能把当前正在运行的数据和变量清理掉呀。这时候提升为GC Root是很恰当的我觉得。至于静态属性,常量什么的作为GC Root毋庸置疑了,他们本来生命周期就是整个应用程序生命周期。
如何判断对象存活与死亡说过了,还需要了解的就是垃圾回收算法 。有四种思想需要提到, 其中有一种最基本的叫做 标记-清除算法。另外很重要的复制算法,是年轻代最合适的。还有一种标记整理算法,是老年代最合适的。最后一种就是分代这个思想。
标记清除就是首先对所有需要回收的对象进行标记,最后统一进行清除。这样的做法效率不高,清理后内存碎片很多,可能导致后期大对象无法分配内存,会经常触发另一次垃圾回收。
复制算法的思想是,将内存分为两块,其中一块保持为空,回收的时候,将存活的对象复制到空的一块,复制完成后,对原来那半内存全部清理。但是java虚拟机并不能留出一半的内存,这样太浪费资源,并且在Java堆中,年轻代里绝大部分内存都是要被回收的。所以Hot Spot中,将年轻代分为8:1:1的Eden,Survivor * 2, 就是一块Eden , 两块Survivor。 所以年轻代的策略,优先使用大的Eden,必须保持一块Survivor为空。回收的时候,将存活的对象,复制到空的Survivor内存区域,清理Eden和刚才使用的Survivor。
如果Survivor放不下存活的对象了,和时候 就该有对象进入老年代了~ 老年代使用标记—整理算法。标记整理思路就是,先标记,然后在回收的时候,将存活的对象移动到一端,将被清理的移动到另一端。然后清理端边界意外的内存。
Java JVM运行时数据区,内存管理和GC垃圾回收的更多相关文章
- Java内存管理:Java内存区域 JVM运行时数据区
转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...
- Java中的字符串常量池和JVM运行时数据区的相关概念
什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...
- JVM运行时数据区及对象在内存中初始化的过程
JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...
- JVM运行时数据区与JVM堆内存模型小结
前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...
- Jvm运行时数据区 —— Java虚拟机结构小记
关于jvm虚拟机的文章网上都讲烂了.尤其是jvm运行时数据区的内容. 抱着眼见为实的想法,自己翻了翻JVM规范,花了点时间稍微梳理了一下. 以下是阅读Java虚拟机规范(Java SE 8版)的第二章 ...
- JVM运行时数据区(二)
4.本地方法栈 本地方法栈与虚拟机栈所发挥的作用是非常相似的,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务. 与Java虚拟机栈一样本地 ...
- Jvm运行时数据区
一:运行时数据区 Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域.这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户 ...
- JVM 运行时数据区 (三)
JVM运行时数据区 运行时数据区由 程序计数器.java虚拟机栈.本地方法栈.堆.方法区 组成: 1.程序计数器 每一个Java线程都有一个程序计数器,用于保存程序执行到当前方法的哪一个指令,它是线程 ...
- JVM总结(一):概述--JVM运行时数据区
大三下,趁着寒假重温一遍JVM,准备在一个系列来总价一下学习JVM的整个过程.争取在接下来的一个星期内更新完这一个系列,然后回家过年. JVM运行时数据区 线程私有的数据区 程序计数器 虚拟机栈 本地 ...
随机推荐
- [转]详解Oracle高级分组函数(ROLLUP, CUBE, GROUPING SETS)
原文地址:http://blog.csdn.net/u014558001/article/details/42387929 本文主要讲解 ROLLUP, CUBE, GROUPING SETS的主要用 ...
- 【转】 Java中的变量赋值和参数传递
原文地址:http://blog.csdn.net/whmii/article/details/3363667 变量赋值和参数传递是java中两个容易让人迷惑的问题.对于原始类型(primitives ...
- ntpd与ntpdate的区别
之前配置ntpd的时候搜到一句话,印象很深刻,也觉得很有标题党的效果,就借鉴为标题了:“我认为有几种人是必须不招聘/裁掉的: 1 用ntpdate代替ntpd的人”但具体原因不太懂,总觉得还是用ntp ...
- Python3 串口模块移植并使用。
想通过 Python去控制串口模块,直接上层就使用一门语言,这样虽然执行效率低一些,但是开发速度加快 通过 buildroot 先移植 Python-serial 模块 x Symbol: BR2_P ...
- Java编程的逻辑 (8) - char的真正含义
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- 两种常用的jquery事件加载的方法 的区别
两种常用的jquery事件加载的方法 $(function(){}); window.onload=function(){} 第一个呢,是在DOM结构渲染完成以后调用的,这时候网页中一些资源还 ...
- 微信小程序——倒计时功能
做小程序项目中,需要做一个倒计时功能,如下图: 记录一下实现步骤: 1.考虑到这个功能可能会有多处用到,所以把倒计时的函数写在utils.js里面: const formatNumber = n =& ...
- Java设计模式(12)迭代模式(Iterator模式)
上了这么多年学,我发现一个问题,好象老师都很喜欢点名,甚至点名都成了某些老师的嗜好,一日不点名,就饭吃不香,觉睡不好似的,我就觉得很奇怪,你的课要是讲的好,同学又怎么会不来听课呢,殊不知:“误人子弟, ...
- [Intellij] 软件设置和常用快捷键
理解Project 和 Module 一个 Project 是由一个或多个 Module 组成,模块之间尽量是处在同一个项目业务的的情况下,彼此之间互相依赖关联.如: Project : spring ...
- [Forward]Sweeping the IDisposable minefield
IDisposable has been around since the beginning of .Net.The basic premise is simple.. Developers don ...