简单理解---JVM虚拟机

java代码执行流程(复杂)hotspot虚拟机: java源码->编译(compile前端编译器)>字节码(class)->类加载器classloader加载类到内存(4种,加载分为5步骤)-→>jvm内存中(5部分)->执行引擎 execution engine(3部分interpreter解释器jitjust in time)即时compiler后端编译gc(garbagecollection)解释执行把字节码指令翻译为机器指令)->当前系统可识别指令->操作系统(os)

类的加载过程

在这里插入图片描述
loading 把class文件(二进制流)(类中的属性 方法 构造 等 )读到方法区中 (jdk7)永久代 (jdk8)元空间
linking(
verify 验证 :保证类的正确性,不会危害虚拟机自身的安全性。
四种验证: 文件格式验证 元数据验证 字节码验证 符号引用验证

prepared 准备: 类属性赋值初始值
resolvel 解析:常量引用 属性引用 解析成真正的引用。

initial:为静态变量赋值。 执行类的static属性 静态代码块 优先加载父类。
use:使用
gc(garbage collect):垃圾回收

4种类加载器:

bootstrap classLoader引导类加载器
c/c++语言编写,是jvm的一部分,加载核心类库,jre/lib库,没有父类加载器,是扩展加载器和应用加载器的父类
extension ClassLoader扩展加载器
java编写加载jre/lib/ext/ 的扩展包
application ClassLoader应用加载器 或者系统加载器
是程序中默认的类加载器java应用类都是由它加载完成java编写负责加载环境变量classpath或者系统属性java.class.path指定下的类库,
默认加载自己编写的java类
CustomClassLoader 还可以自定义编译器,继承

bootstrap classLoader
在这里插入图片描述
extension ClassLoader
在这里插入图片描述

双亲委派机制

概念:
当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归
这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。
作用:
1、**防止重复加载同一个.class。**通过委托去向上面问一问,加载过了,就不用再加载一遍。保证
数据安全。
2、**保证核心.class不能被篡改。**通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,
即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。
这样保证了Class执行安全。

在这里插入图片描述

运行时的内存

在这里插入图片描述

PC寄存器program counter register) :

简介:
存储下一条指令存储地址,执行引擎会根据PC寄存器的编号取出指令执行,如果是native方法就为空
非常小,速度快
线程私有每个线程都有自己的程序计数器
没有内存溢出异常(OOM out of memory Error)没有GC
作用
执行多线程时,CPU要进行多个线程切换,切换后要知道原线程执行的位置

栈及栈溢出及调优

简介:
java虚拟机栈早期叫java栈,每个线程在创建时都会创建一个栈,内部保存了一个一个栈帧,一个
栈帧代表一个java方法,方法执行,就是一次次栈帧出栈和入栈的过程
访问速度仅次于程序计数器
没有GC回收有内存溢出异常(OOM)
方法入栈标识方法的开始,方法出站表示方法的结束
栈帧有大小,大小决定了栈可以存放多少栈帧
java vm栈的大小可以是固定的,也可以是动态的 (动态的 会内存溢出 )
StackOverflowError 栈溢出错误
原因:死循环
调优: 设置set 的 VM options参数设置大一些。

运行原理:

java vm栈有压栈和出栈,遵循先进后出(FILO)或者后进先出(LIFO)原则,正在执行的方法称为当前
栈帧,如果正在执行方法调用了其他方法,对应的新的栈帧就会被创建
放在栈的顶端成为当前栈帧。
方法结束有正常结束return或者异常方式结束。

栈帧内部结构:

1.局部变量表是一个数组,是影响栈帧大小的主要因素是垃圾回收的重要依据
2.存储参数,
3.局部变量,
4.基本数据类型,
5.引用类型和返回值类型

**操作数栈﹐**方法执行过程中,根据字节码指令,向栈中写入和提取数据
动态链接 指向运行常量池的方法引用
DynamicLinkTest使用javap -v DynamicLinkTest.class来观察m1()方法调用
方法返回地址栈帧出站时,把返回值给下一个栈帧,如果异常不会有返回值
StackExecuteDemo使用javap -v观察返回值,异常和正常情况下返回值
在这里插入图片描述

本地方法接口∶

一个native方法就是一个java调用非java代码码的接口
使用c或者c++编写的接口,可以通过java调用
融合不同编码语言为java所用
ctrl+n查看object中的getClass()等方法就是native方法

本地方法栈:

管理本地方法调用的 非Java写的方法
线程私有
可以设置固定大小,也可以动态设置大小
会有StackOverflowError和OutOfMemoryError
与本地方法接口交互

垃圾回收机制

堆:一个jvm实例就是一个进程,一个进程中所有线程共享一个堆,是Java内存管理的核心区域。

新生代和老年代 youngGen oldGen
堆中不包含元空间
最大最小设置成一样的。
堆在jvm启动时初始化,大小也确定(堆的最小值是物理内存的1/64和最大值1/4(新生代中存在
幸存0和1区,jvm实际工作过程中,只有一个区有值,去除一个幸存区大小
),是jyvm最大一块内存空 间
堆的大小可以调节
有GC回收有内存益出异常OOM

堆的内存模型:

(年轻代+老年代+(jdk7永久代 (permanent space)jdk8元空间))
年轻代(youngGen =young genelation space新生代,新生区) :eden survivor0 survivor1 8:1:1
满了之后进行GC 轻量级GC
大多数生命周期很短幸存15次(可以修改)进老年代
老年代(oldGen=old generation space 养老区,老年区): 新生代和老年代 1:2
老年代满了之后进行 重GC
元空间(meta space)实际在将堆时把它独立出去,是方法区的具体实现

在这里插入图片描述
幸存区

调优命令

jps JYM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。
-q只显示进程ID
-m显示主类参数
-显示主类的全名,如果执行的是jar包,显示jar路径
-v输出启动时jvm参数
运行idea中的类
jps -q
jps -m
jps -l
jps -v
jstat, JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程
中的类装载、内存、垃圾收集、JIT编译等运行数据。

运行idea中的类
jps
jstat -help帮助
jstat -options
jps
jstat -class pid 显示加载class的数量,及所占空间等信息。
Loaded :已经装载的类的数量
Bytes:装载类所占用的字节数
Time:装载和载类所花费的时间
jstat -compiler pid 显示VM实时编译(JIT)的数量等信息。
Compiled:编译任务执行数量
Failed:编译任务执行失败数量
Invalid :编译任务执行失效数量
Time:编译务消耗时间
FailedType:最后一个编译失败任务的类型
FailedMethod:最后一个编译失败任务所在的类及方法
jstat -gc pid显示gc相关的堆信息,查看gc的次数,及时间。
soC:年轻代中第一个survivor(幸存区)的容量(字节)
s1C:年轻代中第二个survivor(幸存区)的容量(字节)
sou:年轻代中第一个survivor(幸存区)目前已使用空间(字节)
s1U:年轻代中第二个survivor(幸存区)目前已使用空间(字节)
EC:年轻代中Eden(伊甸园)的容量(字节)
EU:年轻代中Eden(伊甸园)目前已使用空间(字节)

jmap,JVM Memory Map命令用于生成heap dump文件
jmap -help帮助命令
jps
jmap -dump:format=b,file=d:'heap.bin pid
和下面命令结合使用
jhat,JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了
一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看

  jhat d:lheap.bin
http:Hilocalhost:7000/

jstack,用于生或java虚拟机当前时刻的线程快照。
jps
jstack - pid可以查看正在运行和等待的线程
jinfo,JVM Configuration info这个命令作用是实时查看和调整虚拟机运行参数。
jinfo -help
jsp
no option输出全部的参数和系统属性
-flag name输出对应名称的参数
-flag [±]name开启或者关j闭对应名称的参数
-flag name=value 设定对应名称的参数
-flags输出全部的参数
-sysprops输出系统属性
jinfo pid
jinfo -flag paramName pid

特殊情况处理:

当对象要放入eden区发现放不下就会触发ygc,ygc后(eden为空)仍然放不下,说明是大对象,
直接放入老年代
如果老年代也放不下,会进行major gc ->full gc还是放不下就会OOM
YGC后,eden幸存对象加存sO或者s1区幸存对象后,另外一个幸存区放不下,也是直接放入老
年代

堆空间大小设置:

Xms X运行参数ms=memory start是指设定程序启动时占用内存大小。默认为电脑物理内存的
1/64,一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢。
XmxX运行参数mx = memory maximum是指设定程序运行期间最大可占用的内存大小。默认
为电脑物理内存的1/4,如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出
OutOfMemory异常。
自行设置大小-Xmi256m -Xmx256m建议设置一样,避免超过最小值,未达到最大值时GC
不段工作造成额外的系统压力。

对象分配内存的过程:

对象产生(new,反射。。。),直接在eden伊甸园区,eden有大小的,当eden满的会触发
young gc(garbage collect)minor gc(轻量级gc),会把eden区不可达对象回收,剩余可达对象,会把
可达对象放入幸存0区,并且放入对象的age会被+1,清空eden区,然后jvm继续工作,继续产生对
象,直到eden再次放满,再次触发minor gc,会把eden区幸存的和sO区(也要再次判断是否可达)幸存的
对象一起放入s1区,并且所有对象age+1,此时sO又可以称为from区,s1区称为to区,再次清空eden
区,并且清空sO区,然后jvm继续正作,继续产生对象,直到eden再次放满,再次触发minor gc,会把
eden区幸存的和s1区幸存的对象一起放入sO区并且所有对象age+1,此时s1又可以称为from区,sO区
称为to区,以此递归下去。。直到对象的age到达15次,直接放入老年区。。。.。老年区满时
触发magor gc(重量级GC),会触发Full gc(新生代,老年代和方法区都会被GC),仍然对象存不下,就
会触发OOM异常。

GC概念与算法

可达性分析算法

在Java中,是通过可达性分析(Reachabffy Analysis)来判定对象是否存活的。该算法的基本

思路就是通过一些被称为引用链(GC Roots)的对象作为起点,从这些节点开始向下搜索,搜索走过
的路径被称为(Reference Chain),当一个对象到GCRoots没有任何引用链相连时(即从GC Roots
节点到该节点不可达),则证明该对象是不可用的。
Gc概念及作用:
垃圾指运行时没有被任何引用指向的对象,这个对象就是被回收的垃圾,对这些对象的清理就是
GC。
作用:

  1. 释放出更多的内存,防止内溢出
  2. 碎片整理,分配给新的大对象
  3. 保证应用程序
    正常运行

GC类型:

minor gc lyoung gc针对新生代的垃圾的回收,回收相对频繁,会引发短暂STW
触发条件:
eden区满(survivor满不会触发幸存区)
major gc lold gc ICMS(Concurrent Mark Sweep)GC针对老年代的垃圾回收,速度会比ygc
慢10倍以上,会让STW时间更长,如果GC后还是放不下对象,会出现OOM
触发条件:
老年代满
CMS(只回收老年代)和G1的区别(混合GC(不只回收老年))
full gc堆(新生代+老年代)和方法区的垃圾收集,尽量避免full gc,会让STW时间更长
触发条件:
1,System.gc();
2,老年代空间不足
3,方法区(permanet Gen永久代/metaSpace元空间)空间不足
4,通过minor gc后进入老年代的平均大小大于老年代可用内存(age>15)
5,(eden幸存+s0幸存)>s1放老年代,老年代空间又不足(age不一定大于15)

GC算法:

标记清除(mark spveep) :

步骤:
标记:从根节点遍历,在对象的header中标记可达对象(jvm可以标记可达,也可以标记不可达)
清除;从头到尾遍历一遍,回收没有标记的对象
缺点:效率一般,GC时stw用户体验差,产生空间碎片
full gc堆(新生代+老年代)和方法区的垃圾收集,尽量避免full gc,会让SWT时间更长
触发条件:
1,System.gc();
2,老年代空间不足
3,方法区(permanet Gen永久代/metaSpace元空间)空间不足
4,通过minor gc后进入老年代的平均大小大于老年代可用内存
5,(eden幸存+s0幸存)>s1放老年代,老年代空间又不足

复制算法(coping):

内存空间分2块,把一个内存中可达对象,放入另一块内存,然后清除所有,然后轮流交互
优点:效率高,不会产生碎片存活对象少,适合年轻代(生命周期短,存活率低(80%对象都死亡))
类似于拿一个新瓶子装旧酒
缺点:

  1. 消耗内存
  2. 复制对象,维护引用关系复杂(引用的指向变了 )
    在这里插入图片描述

压宿整理(mark sweep compact) :

标记:从根节点遍历,在对象的header中标记可达对象
压缩:把所有存活对象压缩到内存的一端
清除:清除边界外其他所有空间
优点:无碎片 减半内存
缺点:效率低维护引用关系复杂(慢 需要标记引用 移动)

在这里插入图片描述

分代收集算法(Generational Collection):

针对上面算法,和内存模型
年轻代特点:区域相对老年代小,对象声明周期短,存活率低,回收频繁
复制算法
老年代待点:与上面相反
混 合使用

JVM的运行时数据区有哪些?

运行时数据区的定义:Java虚拟机在执行Java程序的过程中会把它所管理的内存划分
为若干个不同的数据区域。
根据JVM规范,标准的JVM运行时数据区包括以下部分:
程序计数器
·Java虚拟机栈
·本地方法栈
堆内存
·方法区
·运行时常量池

栈和堆的区别:

栈是运行时单位,栈解决程序运行时问题,解决如何运行,如何处理数据的
堆是存储的单位,堆解决数据存储问题,数据怎么放,放在什么地方

方法区:

(jdk7永久代permanentGen jdk8元空间metaSpace)
有GC回收有内存溢出异常
类信息 (类,接口,枚举,注解)∶限定名,直接父类限定名,类修饰符,直接接口的有
序列表,field(名称,类型,修饰符等),method(方法的所有信息)
常量final:
静态变量static

对象引用类型:

强引用(strongreference) :

是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。
Object strongReference = new Object();
当内存空间不足时,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会
靠随意回收具有强引用的对象来解决内存不足的问题。(宁死不收)

软引用(SoftReference)

如果一个对象只具有软引用,则内存空间充足时,垃圾回收器就不会回收它;如果内存空间不
足了,就会回收这些对象的内存。(不足则收) 缓存redis

弱引用(WeakReference)

在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当
前内存空间足够与否,都会回收它的内存。(发现就收) 缓存redis

虚引用(PhantomReference)

如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器
回收。虚引用顾名思义,就是形同虚设。目的在这个对象被回收时收到一个系统通知(形同虚设)

使用场景:
强引用 大部分场景下使用99%的是该场景
软和弱引用 缓存场景下使用
虚引用 对象引用跟踪

触发FullGC

除直接调用System.gc外,触发Full GC执行的情况有如下四种。
1.旧生代空间不足
旧生代空间只有在新生代对象转入及创建为大对象、大数组时才会出现不足的现象,当执行Full GC后空
间仍然不足,则抛出如下错误:
java.lang.OutOfMemoryError: Java heap space
为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在新生
代多存活一段时间及不要创建过大的对象及数组。
2.Permanet Generation空间满
PermanetGeneration中存放的为一些class的信息等,当系统中要加载的类、反射的类和调用的方法较
多时,Permanet Generation可能会被占满,在未配置为采用CMSGc的情况下会执行Full GC。如果经
过Full GC仍然回收不了,那么JVM会抛出如下错误信息:
java.lang.OutOfMemoryError:PermGen space
为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC.
3.CMS GC时出现promotion failed和concurrent mode failure
对于采用CMS进行旧生代GC的程序而言,尤其要注意GC日志中是否有promotion failed和concurrent
mode failure两种状况,当这两种状况出现时可能会触发Full GC。
promotionfailed是在进行Minor GC时,survivor space放不下、对象只能放入旧生代,而此时旧生代
也放不下造成的; concurrent mode failure是在执行CMS GC的过程中同时有对象要放入旧生代,而此
时旧生代空间不足造成的。
应对措施为:增大survivorspace、旧生代空间或调低触发并发GC的比率,但在JDK5.0+、6.0+的版本
中有可能会由于DK的bug29导致CMS在remark完毕后很久才触发sweeping动作。对于这种状况,可

什么是Java虚拟机?为什么ava被称作是"平台无关的编程语言”?

Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节
码文件。Java被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或
者是重新编译。Java虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其他特性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值