JVM

46 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天

1、栈

image-20221015110347536

图 为什么main()先执行,最后结束~

====

栈:先进后出 桶:后进先出

队列:先进先出( FIFO : First Input First Output )

栈:栈内存,主管程序的运行,生命周期和线程同步;

线程结束,栈内存也就是释放,对于栈来说,不存在垃圾回收问题

一旦线程结束,栈就Over!

栈内存中:

8大基本类型+对象引用+实例的方法

栈运行原理:栈帧

栈满了: StackOverflowError

图 栈的位置示意图

image-20221015111131766

图 栈帧图解 栈底部子帧指向上一个栈的方法 上一个栈的父帧指向栈底部方法

image-20221015112251901

2、三种JVM

HotSpot 使用最多

JRockit BEA

J9 vm IBM

3、堆

Heap, 一个JVM 只有一个堆内存,堆内存的大小可以调节的。

类加载器读取了类文件后,一般会把什么东西放在对里面? 类的具体实例,

堆内存划分:

1)新生区 :Eden、S0、S1。对象在这里诞生、成长、甚至死亡

Eden:所有对象都是在eden区new出来的。

2)老年区

3)永久区:jdk1.8以后,叫元空间(方法区在这里,常量池在方法区里)。这个区域是常驻内存的,用来存放jdk自身携带的class对象。

image-20221015114334923

GC垃圾回收,主要在伊甸园区和养老区~ 假设内存满了,OOM, 堆内存不够!

新生区

  • 类: 诞生 和成长的地方,甚至死亡;
  • 伊甸园区: 所有的对象都在 伊甸园区 new出来的!
  • 幸存者区(0.1)

老生区

image-20221015145106533

真理:经过研究,70%-99%的对象都是临时对象!|

永久区

这个区域常驻内存的,用来存放JDK自身携带的Class对象,interface元数据,存储的是java运行的一些环境类信息,这个区域不存在垃圾回收!关闭VM虚拟就会释放这个区域的内存!

一个启动类,加载了大量的第三方jar包,tomcat部署了太多的应用,大量生成反射类,不断的被类加载,直到内存满,就会出现OOM;

  • jdk1.6之前: 永久代,常量池在方法区;
  • jkd1.7 : 永久代,但是慢慢的退化了,去永久带,常量池在堆中;
  • jdk1.8以后:无永久代,常量池在元空间

image-20221015151459424

image-20221015151918403

元空间:逻辑上存在,物理实际上不存在

在一个项目中,突然出现了OOM的故障,那么该如何排除

  • 能够看到代码第几行出错:内存快照分析工具,MAT, Jprofiler

  • Debug,一行一行分析代码!

  • MAT,Jprofiler作用:

    1.分析Dump内存文件,快速定位内存泄漏

    2.获得堆中的数据

    3.获得大的对象

遇到OOM问题怎么解决的?

  1. 尝试扩大堆内存查看结果

     -Xms1024m -Xmx1024m -XX:+PrintGDetails
    
  2. 分析内存,看一下那个地方出现了问题