今天讲:
别逃避,是时候来给JVM一记重锤了!
为什么写这个主题呢?
之前看到不少同学在讨论,
今天呢灯塔君抽出点时间来帮大家整理一下关于JVM的一些知识点
一.JVM是什么?
JVM,即Java Virtual Machine ,Java虚拟机 运行在操作系统之上的虚拟的计算机 。我们主要研究的是 HotSpot VM JDK自带的虚拟机,这个虚拟机有两个很好的优点: 准确式GC + 热点代码探测技术。所谓准确式GC,就是让JVM知道内存中某位置数据的类型什么。比如当前内存位置中的数据究竟是一个整型变量还是一个引用类型。这样JVM可以很快确定所有引用类型的位置,从而更有针对性的进行GC roots枚举。JVM进行一段代码是不是热点代码,是不是需要触发即时编译,这样的行为称为热点探测。
Java语言最重要的特点之一:跨平台使用,正是由于JVM的存在。
二.JVM怎么来?
我们都知道,要做Java开发,必须在你的电脑上安装JDK才行,安装JDK之后里面会有一个JRE的目录,JRE提供了软件环境----JVM。
三.JVM虚拟机内存结构
JVM虚拟机将其内存分为程序计数器、虚拟机栈、本地方法栈、java堆、方法区。
程序计数器:是一块私有的内存空间,比较小。主要记录下一条要运行的命令。
虚拟机栈:也是线程私有的内存空间,和java线程同一时间创建,主要用来保存局部变量、部分结果、并参与方法的调用和返回。(虚拟机栈运行时使用一种叫“栈帧”的数据结构保存上下文数据。)
本地方法栈:虚拟机栈用于管理java函数的调用,本地方法栈用于管理本地方法的调用(用C实现的方法)
java堆:所有的对象、数组都是在堆中分配空间。
堆分为:新生代、老年代。
新生代:存放刚刚产生的对象和年轻对象。新生代分为:e’den(对象刚创建时)、survivor space()、1(至少被GC一次)。
方法区(永久区):被JVM中的所有线程共享(独立于java堆的内存空间)。主要保存的是类的元数据(类的类型信息、常量池、域信息、方法信息:存放常量和类的定义信息)。GC回收时,只回收永久区中常量池的回收(未被引用的常量),再就是对类元数据的回收。
四.对象的堆内存布局
在HotSpot虚拟机中,对象在堆内存的布局分为三个区域,分别是对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)。
对象头:对象头包括两部分信息分别是Mark World和元数据指针,Mark World用于存储对象运行时的数据,比如HashCode、锁状态标志、GC分代年龄等。而元数据指针用于指向方法区的中目标类的类型信息,通过元数据指针可以确定对象的具体类型。
实例数据:用于存储对象中的各种类型的字段信息(包括从父类继承来的)。
对齐填充:对齐填充不一定存在,起到了占位符的作用,没有特别的含义。
五.垃圾回收(GC)
GC是jvm的垃圾回收,当实例化一个java对象的时候jvm为此对象分配一块内存,当此对象不再被使用时,由jvm自动回收此内存块。不用人为的释放内存,降低了内存溢出的风险。
GC算法通常有两种,一是引用计数,当对象创建、引用时该对象的计数增加,引用超出作用域或者对象为空的时候,此计数减少。当计数为0的时候此对象可以回收。二是对象引用遍历,也称向图法。就是从根开始沿着整个对象图遍历,标记可到达的对象。再通过扫描整个堆栈处理不可到达的对象。
这两种算法对应了多种实现机制
1.标记-清除
2.标记-压缩
这两种机制是对不可到达的对象进行清理、压缩处理。
3.复制机制
这种机制将堆栈分为两个区域,称为半空间。每次使用一半的空间,生成的新对象在一个空间GC时将可到达的对象复制到另一个空间,从而实现堆栈的压缩。
4.增量机制
这种机制是将内存分为多个区域,每次从一个区域进行垃圾回收。
5.分代机制
这个一个比较常用的机制,这种收集机制是将堆栈分为两个或多个区域。用于存放不同寿命的对象,根据对象的使用频率分配不同寿命的区域。
以上机制称为串行GC,GC的时候会造成程序的暂停,jvm还有基于多线程的GC,称为并行GC和并发GC,他们的扫描复制都是在多线程的基础上进行的不会造成程序的暂停,适用于多cpu和对暂停时间要求较短的应用程序。是server级默认的GC机制。
6.为什么要掌握JVM?
如果灯塔君换种方式问你:
当你的程序出现OOM的时候怎么处理?
当我们出现内存泄漏、内存溢出的时候我们不应该直接想到用-Xms去设置内存 或者栈的-Xss或者restart来解决,而是更应该去想想:为什么会出现OOM?是什么原因导致?怎么优化?怎么避免?。
其实灯塔君认为,我们为什么要去学习JVM呢?两点考虑:从感性角度来看应该是:知其然,知其所以然,从理性角度来分析:我们更应该看重的是JVM的准确式内存管理。不管是为了加薪,还是为了过面试或者为了知识栈储备,我们都应该掌握JVM。