JVM脑图

JVM
类装载器
根加载器,像 Object 这些类,在一启动的时候,就通过 Bootstrap 启动类加载器加入
到了 jvm ,所以可以直接使用
扩展类加载器,在 jdk 不停的更新途中,加入了很多新的 jar 包,这些 jar 包就使用扩
展类加载器 Extension 加入到了 jvm
系统类加载器,自己在 java 项目中创建的 class 类,都会通过 AppClassLoader 系统类
加载器,加载当前应用的 classpath 的所有类进入到 jvm
双亲委派
一个类的加载先从根加载器找,根加载器找不到就去扩展类加载器找,扩展类找
不到就去系统类加载器中找。
沙箱安全机制
双亲委派机制就是为了保证沙箱安全机制,就不让人干坏事,不能替换掉 java
身自带的一些类
线程私有: native 本地方法
native 是一个关键字
有声明, java 无实现,是使用的 C 语言实现的第三方函数库,
线程私有: PC 寄存器:程序计数器
行号计数器,用来存储执行到了第几行,多线程环境下会出现时间争抢,如果当前
线程时间片用完,那么就需要等待获取到新的时间片来进行执行,那么从等待重新
开始执行的时候,从哪一行开始执行就是用程序计数器来决定的
记录了方法之间的调用和执行情况,类似排版值日表,用来存储指向下一条指令的
地址,也就是将要执行的指令代码,它是当前线程所执行的字节码的行号指示器
线程私有: stack :栈
栈管运行,堆管存储
栈主管 java 程序的运行,在创建线程时创建,在线程结束时栈也释放,栈不存在垃
圾回收问题,只要线程一结束该栈就 Over ,声明周期和线程一致,是线程私有的
8 种基本类型的变量 + 对象的引用变量 + 实例方法都是在函数的栈内存中分配
栈帧钟主要存储三类数据
1 :本地变量,输入参数和输出参数以及方法内的变量
2 :栈操作,记录出栈,入栈的操作
3 :栈帧数据,包括类文件,方法等等 java 方法 = 栈帧
每个方法执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链
接、方法出口等信息,每一个方法从调用直至执行完毕的过程,就对应着一个栈帧
在虚拟机钟入栈到出栈的过程,栈帧的大小和具体 jvm 的实现有关,通常在
256K~756K 之间,约等于 1Mb 左右
java.lang.StackOverFlowError SOF :把栈撑爆了,是一个 Error 错误
线程共享:方法区
存在垃圾回收
方法区不是专门放方法的地方
供各线程共享的运行时内存区域,它存储了每一个类的结构信息,运行时常量池、
字段和方法数据、构造函数和普通方法的字节码内容
方法区是规范,在不同虚拟机里面实现是不一样的,最典型的就是永久代和元空间
空调 k1 = new 格力()
list list = new Arraylist ()
java 7 以前是:方法区 f = new 永久代
java 8 以后是:方法区 f = new 元空间
所以方法区是一个规范, new 的后面是具体的实现
线程共享: heap :堆
新生代
伊甸区: Eden 元区
new 出来的第一次都存放在这个区域
Eden 区满了会开启 ygc GC ,执行 ygc 后,大部门对象都会被 kill 掉,没有被
kill 掉的幸存者就会转移到幸存者 0
幸存者 0 区: Survivor 0
接收没有被 ygc kill 掉的对象,幸存者 0 区和 1 区会进行交换,保证 0 1 两个区
域一个存放活着的对象,一个啥都不存
幸存者 1 区: Survivor 1
GC 15 次(默认值 15 )没被 kill 掉的会转移到老年代
交换
from 区和 to 区,他们的位置和名分,不是固定的,每次 GC 后会交换,谁空谁
to
老年代
如果老年代区域也满了,就会开启 full gc = FGC GC ,如果 full gc 多次,发现
空间没办法腾出来,那么 jvm 就报 OOM 堆内存溢出异常 理论
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾
回收器收集,结束生命。新生区又分为两部分:伊甸区和幸存者区,所有的类都
是在伊甸区被 new 出来的。幸存区有两个: 0 区和 1 区。当伊甸园的空间用完时,
程序又需要创建对象, JVM 的垃圾回收器将对伊甸园区进行垃圾回收 Minor GC
GC ,将伊甸园区中的不再被其它对象所引用的对象进行销毁。然后伊甸园中
的剩余对象移动到幸存者 0 区,如果幸存者 0 区也满了,再对该区进行垃圾回
收,然后移动到 1 区,那如果 1 区也满了呢?再移动到养老区,若养老区也满
了,那么这个时候将产生 MajorGC FULLGC ,进行养老区的内存清理,若养老区
执行了 Full gc 之后依然无法进行对象的保存,就会产生 OOM
"OutOfMemoryError"
jdk8 以后元空间 /jdk7 之前永久代
堆内存调优
-Xms :设置初始分配大小,默认为物理内存的 1 / 64
-Xmx :最大分配内存,默认为物理内存的 1 / 4
-XX:+PrintGCDetails :输出详情的 GC 处理日志
实践经验
生产环境上的 java 应用, JVM -Xmx -Xms 两个参数的值必须一致,防止内
存忽高忽低产生停顿
java.lang.OutofMemoryError java heap space :堆内存溢出
GC (分代收集算法)
次数上频繁收集 Young
次数上较少收集 Old
基本不动元空间
GC 4 大算法
引用计数法
jvm 实现不采用这种方式
有一个计数器去记录每个对象被引用的次数
缺点:较难处理循环引用,有个计数器消耗性能
复制算法
年轻代使用的垃圾回收算法就是复制算法
复制算法的基本思想就是将内存分为两快( Eden 区和 from 区是一快 to 也是
一快),每次只用其中一快,当这一快内存用完,就将还活着的对象复制到
另外一快上面,复制算法不会产生内存碎片 因为 Eden 区对象一般存活率较低,一般的,使用两块 10% 的内存作为空闲和
活动区间,而另外 80% 的内存,则是用来给新建对象分配内存的,一旦发生
GC ,将 10% from 活动区间与另外 80% 中存货的 Eden 对象转移到 10% to
闲空间,接下来,将之前 90% 的内存全部释放,以此类推
优点:速度快
缺点:浪费空间 浪费了一半内存,这太要命了
标记清除
老年代使用的就是标记清除与标记整理的混合实现
算法分成标记和清除两个阶段
先标记出要回收的对象
然后统一回收这些对象
缺点:
内存碎片过多
速度没复制算法快,有标记和清除两个操作
优点:
不需要额外的空间
标记压缩
老年代使用的就是标记清除与标记整理的混合实现
也叫标记清除 + 标记整理算法,比标记清除多了一步整理的步骤
缺点:
速度慢
优点:
不会浪费空间和产生内存碎片
JDK9 之后
JAVA 9 的默认垃圾回收器
G1 垃圾回收器
G1 将新生代,老年代的物理空间划分取消了,这样我们再也不用单独的空
间对每个代进行设置了,不用担心每个代内存是否足够。
G1 算法将堆划分为若干个区域(
Region ),它仍然属于分代收集器
https://www.kancloud.cn/luoyoub/jvm-note/2255980

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱敲代码的小松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值