深入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遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状态和激情都要 ...
随机推荐
- Java Web学习总结(1)Tomcat使用教程
一,简介 Tomcat是一个实现了JAVA EE标准的最小的WEB服务器,是Apache 软件基金会的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.因 ...
- Python基础教程(018)--官方解释器交互运行
前言: 在交互式运行Python程序 内容 在Python的shell中直接输入Python的代码,可以立即执行结果 交互式运行Python的优缺点 1,缺点--代码不能保存 2,不适合运行太大的程序 ...
- AcWing 260. 买票 (树状数组+二分)打卡
题目:https://www.acwing.com/problem/content/description/262/ 题意:给定一个队伍,每个人过来的时候可以插队,每个人会输入一个插入到哪个位置,但是 ...
- python中的单例模式及其实现
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在. 当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. 比如, ...
- English-Words with 'ir'
hire thirty thirteen third sir birthday shirt stir circle dirty skirt affirm affirmation affirmable ...
- 对GridFS数据进行分片
On this page files 集合 chunks 集合 在对 GridFS 存储进行分片时,需要注意以下的情况: files 集合 大多数情况下不需要对 files 集合进行分片,这个集合通常 ...
- EasyUI的datagrid表格行高度增加
这里以easyui的default样式为例: 找到easyui--->themes-->default-->easyui.css-->Ctrl+F找到.datagrid-row ...
- SSH服务搭建、账号密码登录远程Linux虚拟机、基于密钥的安全验证(Windows_Xshell,Linux)
问题1:如果是两台虚拟机ping不同且其中一个虚拟机是克隆的另一个,需要更改一下MAC地址,关机状态下 一> "编辑虚拟机设置" 一>" 网络适配器" ...
- C++中初始化列表的使用
1,初始化列表是在 C++ 中才引入的: 2,以“类中是否可以定义 const 成员?”这个问题来引入初始化列表: 1,const 这个关键字可以定义真正意义上的常量,也可以在某些情况下定义只读变量: ...
- Oracle学习笔记<4>
多表查询 1.什么是多表查询? 一次select语句需要查询的内容来自于不止一张表. 同时从多张表中查询数据. 单表查询: select id,last_name,salary from s_emp ...