深入java虚拟机学习笔记(一)
学习java学到最后都要很熟悉jvm,懂得了java的运行机制,查找问题就会很快了,一般我们都是会用,还到不了精通的地步,虽说我也是个多年的java工程师,但也没有很好的掌握jvm,最近换了一家公司,之前的算是被雪藏三年,一直未于外界接触,现在我要重新拾起来,不能满足只是会用java,也要懂得其运行原理。
学习jvm我们要知道它有哪几部分构成,各部分作用是什么:
- 运行时数据区域
- 程序计数器
- java虚拟机栈
- 本地方法栈
- java堆
- 方法区
- 运行时常量池
- 对象的创建
程序计数器
指令执行的指向,是一块很小的内存空间,每个线程都有一个独立的程序计数器,互不影响,独立存储;如果执行native方法,则计数器为空;这个内存空间不存在OutOfMemoryError的情况。
Java虚拟机栈
它与程序计数器一样,是线程私有的,生命周期也同线程相同。它是java方法执行的内存模型,每个方法在执行时会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息,每一个方法从调用到执行完成的过程就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
java虚拟机规范中对这个区域定了两种异常情况:1.线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常。
2.虚拟机动态扩展时,无法申请到足够的内存,就会抛出OutOfMemoryError异常。
本地方法栈
本地方法栈与虚拟机栈所发挥的作用非常相似,区别就是虚拟机栈执行java方法,本地方法栈则为虚拟机使用native方法,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常
java堆
java堆是jvm所管理的内存中最大的一块,java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例以及数据组都在这里分配内存。但随着jit编译器的发展与逃逸分析技术成熟,在堆上分配也不那么绝对了。
java堆是垃圾回收的主要区域,也称为GC堆。从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以java堆中细分为:新生代和老年代,再细分为:Eden空间,FromSurvivor空间,To Survivor空间等。无论哪个区域,存储的仍是对象实例,进一步划分的目的是为了更好的回收内存、更快的分配内存。如果堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
方法区
方法区与java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。虽然jvm规范把方法区描述为堆的一个逻辑部分,但它有一个别名Non-Heap,目的就是与堆分开。
java方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常。
运行时常量池
运行时常量池是方法区的一部分,class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
常量池是java方法区的一部分,无法满足内存分配需求时,将会抛出OutOfMemoryError异常。
对象的创建:
虚拟机遇到一条new指令时,首先要检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过,如果没有就执行相应的类加载过程。
可达性算法:
算法的基本思想就是通过GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象没有到gc roots没有任何引用链相连时,则证明对象是不可用的。
引用类型:
强引用:Object object = new Object();这类的引用,只要强引用还存在,gc永运不会回收掉被引用对象。
软引用:描述一些还有用但并非必需的对象。在系统未发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这些回收没有足够的内存,才会抛出内存溢出异常。
弱引用:也是用来描述非必需对象的,比前两者更弱,被弱引用的关联对象只能生存到下一次垃圾收集发生之前。当gc时,无论内存是否足够,都会回收被弱引用关联的对象。
虚引用:最弱的引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
对象何时回收:
对象回收至少要经历两次标记过程,如果对象在进行可达性分析后发现没有gc roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,条件就是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为"没有必要执行"。
如果这个对象没有必要执行finalize()方法,那会被放在F-Queue的队列之中,并在稍后由一个虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里的执行是触发方法,并不承诺会等待它运行结束,这样是因为在finalize()中万一执行缓慢或死循环了,那F-Queue就会永久处于等待,甚至内存回收系统崩溃。如果对象在finalize()中逃过,那它就不会被回收。
无用的类:
该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
加载该类的ClassLoader已经被回收。
该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
垃圾回收器算法:
标记-清除算法:首先标记出所有需要回收的对象,在标记完成后统一回收。两个不足:1.效率不高2.空间问题,这种会产生大量不连续的内存碎片,如果有大对象分配时,无法找到连续内存而不得不提前触发另一次的垃圾收集动作。
复制算法:为了解决效率问题,一种称为“复制”的收集算法出现了,它把内存按容量划分为大小相等的两块,每次使用其中一块,当这块用完了就把对象复制到另外一块上面,然后把已使用过的内存空间一次清理掉。现在的商业虚拟机都采用这种算法,但并不是按1:1的比例来划分内存空间的,它是将内存分为一个较大的Eden空间和两个较小的Survivor空间,每次只使用Eden和一个Survivor。默认是8:1:1。
标记-整理算法:算法同第一种,但后续不是直接对可回收的对象进行清理,而是让所有存活对象都向一端移动,然后直接清理掉端边界以外的内存。
分代收集算法:一般将java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
深入java虚拟机学习笔记(一)的更多相关文章
- 《深入Java虚拟机学习笔记》- 第19章 方法的调用与返回
<深入Java虚拟机学习笔记>- 第19章 方法的调用与返回
- 《深入Java虚拟机学习笔记》- 第16章 控制流
<深入Java虚拟机学习笔记>- 第16章 控制流
- 《深入Java虚拟机学习笔记》- 第17章 异常
<深入Java虚拟机学习笔记>- 第17章 异常
- 《深入Java虚拟机学习笔记》- 第13章 逻辑运算
<深入Java虚拟机学习笔记>- 第13章 浮点运算
- 《深入Java虚拟机学习笔记》- 第14章 浮点运算
<深入Java虚拟机学习笔记>- 第13章 浮点运算
- 《深入Java虚拟机学习笔记》- 第8章 连接模型
Java虚拟机学习笔记(八)连接模型
- 《深入Java虚拟机学习笔记》- 第4章 网络移动性
Java虚拟机学习笔记(四)网络移动性
- 《深入Java虚拟机学习笔记》- 第2章 平台无关
Java虚拟机学习笔记(二)平台无关
- Java虚拟机学习笔记——JVM垃圾回收机制
Java虚拟机学习笔记——JVM垃圾回收机制 Java垃圾回收基于虚拟机的自动内存管理机制,我们不需要为每一个对象进行释放内存,不容易发生内存泄漏和内存溢出问题. 但是自动内存管理机制不是万能药,我们 ...
- 深入理解java虚拟机学习笔记(一)JVM内存模型
上周末搬家后,家里的宽带一直没弄好,跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状态和激情都要 ...
随机推荐
- LOJ 2721 「NOI2018」屠龙勇士——扩展中国剩余定理
题目:https://loj.ac/problem/2721 1.注意别一输入 p[ i ] 就 a[ i ] %= p[ i ] ,因为在 multiset 里找的时候还需要真实值. 2.注意用 m ...
- SQL案例
1.字符串去掉空格 原因:(1)空格 (2)制表符 )); ); ); INSERT INTO #temp SELECT '明天我就结婚了 '; DROP TABLE #temp; --1.2 采用A ...
- Design:设计(活动)百科
ylbtech-Design:设计(活动)百科 设计是把一种设想通过合理的规划.周密的计划.通过各种感觉形式传达出来的过程.人类通过劳动改造世界,创造文明,创造物质财富和精神财富,而最基础.最主要的创 ...
- C#-Newtonsoft.Json遍历并修改JSON
遍历 JObject:https://www.newtonsoft.com/json/help/html/JObjectProperties.htm 遍历 JArray: string json = ...
- Java反射实现Servlet处理多个请求--server分发
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.serv ...
- 正则search与match的区别
import re # #1.search和match的区别 # pattern = re.compile(r'\d+') # #match从头开始匹配 # m = pattern.match('on ...
- static_cast关键字 dynamic_cast关键字
前言 说起C++中的继承.多态.虚函数等概念,可能很多同学都有所了解,但是要说真正熟知的同学可能就不是很多了.最近在编程过程中了解到C++类型的层次转换(这就涉及到了多态和继承的相关概率),通常C语言 ...
- 动画FPS计算
1.chrome的debug 2.PerformanceObserver var observer = new PerformanceObserver(function (list) { var pe ...
- f-strings格式化输出
python3.6后加入标准库的格式化输出新的写法 不区分大小写,f,F都可以 可以加入表达式 s1 = 'haha' s = f'python{s1.upper()}' l1 = ['小明', 18 ...
- Codeforces Fix a Tree
Fix a Tree time limit per test2 seconds A tree is an undirected connected graph without cycles. Let' ...