JVMJava虚拟机不来看看吗?
Posted Putarmor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVMJava虚拟机不来看看吗?相关的知识,希望对你有一定的参考价值。
JVM干货
JVM(Java Virtual Machine)称为Java虚拟机,虚拟机指的是通过软件模拟的具有完整硬件功能的、运行在一个完全隔离的环境中的完整计算机系统。
Java语言在一次编写完成后,能够运行在任意平台,这是因为JVM做了兼容性处理。
一、JVM内存布局
堆【线程共享】
实例化的所有对象也就是我们new Object()对象都是存在此区域,堆也是JVM内存中最大的一块区域,JVM垃圾回收就是针对此区域。
从上图可以看出:
堆可以划分为:新生代和老年代 新生代,新生代又可以划分3个区域
新生代
:第一次创建的对象会被分配到新生代区域
老年代
:经历了一定次数垃圾回收后,依然存活的对象就会被移动到老年代;大对象在创建时候也会直接被分配到老年代(无需经过垃圾回收的洗礼)【默认执行次数15次,每一次GC后加1】
那么为什么大对象创建时会直接进入到老年代呢?
答:大对象初始化比较耗时,放在新生代的话,频繁创建和销毁会带来一定性能开销,因而最好的方式就是将大对象存入GC频率较低的老年代。
对于新生代而言:
Eden区占80%
S0占10%
S1占10%
这样新生代的内存利用率可以达到90%,分析:假如开始空出S0,只在Eden和S1中创建对象,在GC之后,将存活的对象全部移动到S0中,清空Eden和S0;下一次在Eden和S0中创建对象,将GC后存活的对象移动到S1,这样一直操作下去,保证每一次新生代使用率可以到达90%,这样性能比较高。
JVM参数调优
-Xmx10m:设置堆最大容量
-Xms10m:设置堆最小容量
小技巧:将堆最大容量和堆最小容量设置相同,这样可以防止堆扩容造成的抖动
设置方式:IDEA安装路径bin目录下
Java虚拟机栈【线程私有】
JVM栈中存在四部分信息:
1.局部变量:八大基础数据类型,对象的引用;
2.操作栈:每个方法都对应一个操作栈,从入栈到出栈算方法的生命周期;
3.动态连接:指向常量池的方法引用;
4.方法返回值:PC寄存器的地址;(PC寄存器类似于离CPU最近的L1缓存)
本地方法栈【线程私有】
和JVM栈比较相似,但是JVM栈是给Java语言和JVM使用的,而本地方法栈是为本地方法(c/c++)区服务的。
程序计数器【线程私有】
记录线程执行的行号(线程时间片结束后,下一次恢复执行从什么未知开始,这是程序计数器要做的)。
方法区(1.7)/元空间(1.8)【线程共享】
JDK1.7方法区所包含的信息:运行时常量池、字符串常量池、类的元信息;
JDK1.8变成元空间:逻辑上属于JVM,但实际上已成为了本地空间(本地内存),不再受JVM最大内存的制约,此外相对于1.7的变化是,将字符串常量池移到了堆区域中
。
二、类加载机制
类加载(Class Loading)过程大致分为三步:加载 链接 初始化,七张链接又可以分为三步:效验 准备 解析
加载(去机场):1.根据类路径全名加载二进制流 2.将静态存储结构转换为运行时的数据结构 3.在内存中生成一个此类的方法入口
效验(安检) 1.文件格式效验 2.字节码效验
准备(等候登机) 将类中静态属性在内存中分配(此时在内存中进行类型初始化,而不是变量初始化,比如int类型为0)
解析(找到自己位置) 初始化final修饰的常量,将常量的符号引用替换成直接引用的过程。
初始化(准备起飞) 将jvm执行权转移到自己写的程序,开始执行构造函数
在这里说一下三个概念:字面量 符号引用 直接引用
字面量:字符串(jdk1.7后移动到堆中)、final常量、基本数据类型的值
符号引用:类、方法、字段的完全限定名(全路径名称,如包+类+静态属性Thread.TestDemo.count)
直接引用:将符号引用直接加载到内存中(根据引用直接指向内存中的对象)
双亲委派模型
如果一个类收到了类加载的请求,它首先不会去尝试加载这个类,而是把这个请求委派给父类加载器,当找不到父类时自己才尝试加载。每一个层次的类加载器都是如此,因此所有的加载请求都始终该传送到最顶层的启动加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围内没有找到所需的类)时,子类加载器才会去自己完成加载。
双亲委派模型加载流程
优点:
唯一性:父类只去执行加载一次
安全性:子类加载时会向上寻找父类,父类一般是系统的类,这避免了去加载自定义与系统类同名类,一定程度上保证了安全性。
缺点:
由于父类是先于子类加载的,因此父类最开始无法去调用子类的属性及方法等,这是双亲委派模型的缺点
破坏双亲委派模型历程
:
第一次:jdk1.2时提出了双亲委派模型,为了兼容以前的代码,出现了破坏双亲委派模型的场景;
第二次:因为双亲委派模型自身缺点,因此破坏;
第三次:对于热更新(热部署)导致双亲委派模型又一次破坏。
三、垃圾回收机制
死亡对象判断算法(垃圾)
引用计数器算法
给每个对象创建一个计数器,当有程序引用该对象时候,计数器+1,不使用的时候计数器-1,当计数器为0时,表明该对象没人使用,此时可以将它归为死亡对象并等待垃圾回收器的回收。
引用计数器算法缺点:存在循环引用的问题。HotSpot默认的垃圾回收器不是引用计数器算法
可达性分析算法(HotSpot默认算法)
核心思想:通过一系列称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索走过的路径称为“引用链”,当一个对象到GC Roots没有任何引用链相连时,表示从GC Roots到对象不可达,证明对象是不可用的。
不可达的对象一定会被GC吗?
垃圾回收算法
标记清除算法
利用可达性分析算法判定存活的对象与死亡的对象,
标记清除算法缺点
: 标记和清除两个部分效率都不高;标记清除后会产生大量不连续的内存碎片,空间碎片太多,导致以后在程序运行中创建大的对象时,无法找到空间较大的连续内存,被迫触发一次垃圾回收。
复制算法(新生代回收算法)
优点:性能比较高
缺点:内存使用率低
HotSpit针对于内存使用率低的问题进行优化,也就是之前提到的新生代区域与被划分为Eden、S0和S1!!!
标记整理算法(老年代回收算法)
复制收集算法在对象存活率比较高时会进行大量的复制操作,效率低下,因此老年代不能去使用标记整理算法;
针对老年代自身的特点,提出标记整理算法
;标记过程与标记清除过程一致,但是后续不是对可回收对象直接进行清理,而是让所有存活对象都向一端移动,然后清理掉边界以外的内存。
垃圾回收器
目前使用最多的是CMS垃圾回收器,最有潜力的垃圾回收器是G1
Serial:第一代回收器(单线程串行),使用它进行垃圾收集时,必须暂停其他的所有工作线程,直到它收集结束(Stop The wORLD);使用的是复制算法
Serial Old:使用的是标记整理算法
ParNew:并行执行垃圾回收器(相当于Serial多线程版本)
Parallel Scavenge:并发垃圾回收器(新生代),以吞吐量作为主要依据进行垃圾回收,采用复制算法
Parallel Old:并发垃圾回收器(老生代),采用标记整理算法
CMS:Concurrent Mark Sweep
优点:并发收集、低停顿(垃圾回收时间短)
G1:Garbage First收集器是用在堆内存区域很大的情况下,把堆划分为很多gegion,然后并行地进行垃圾回收,它是jdk11的默认垃圾收集器。
G1回收region时候基本不会STW,而是会基于most garbage优先回收(整体来看基于标记清除算法,从局部(两个region)来看基于复制算法)的策略对region进行垃圾回收。
四、JMM(Java内存模型)
JVM定义了一种Java内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,这样做的目的是让Java程序在各种平台下都能达到一致的内存访问效果。
主要目的是定义程序中各个变量的访问规则。
Java内存模型规定所有变量都存储在主内存中,每个线程还有自己的工作内存。
线程的工作内存中保存了被该线程使用到的变量的拷贝(从主内存中拷贝过来的值),线程对变量的所有操作都必须在工作内存中执行,而不能直接在主内存中进行。
不同线程之间无法直接访问对方工作内存的变量,线程间变量值的传递都要通过主内存
来完成。
主内存主要对应Java堆中实例数据部分。工作内存对应于虚拟机栈中部分区域。
线程、主内存、工作内存之间的交互关系如下:
内存间交互操作
lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read(读取):作用于主内存变量,把主内存的一个变量读取到工作内存中。
load(载入):作用于工作内存,把read操作读取到工作内存的变量载入到工作内存的变量副本中
use(使用):作用于工作内存的变量,把工作内存中的变量值传递给一个执行引擎。
assign(赋值):作用于工作内存的变量。把执行引擎接收到的值赋值给工作内存的变量。
store(存储):把工作内存的变量的值传递给主内存
write(写入):把store操作的值入到主内存的变量中
JMM三大特征:
可见性:
当一个共享变量在多个本地内存中有副本时,如果一个本地内存修改了该变量的副本,其他变量应该能够看到修改后的值,此为可见性。
有序性:
保证线程的有序执行,这个为有序性。(保证线程安全)
原子性:
要么全部成功,要么全部失败
希望各位老铁点赞鼓励…
以上是关于JVMJava虚拟机不来看看吗?的主要内容,如果未能解决你的问题,请参考以下文章