JVM

一、JVM的体系结构

  1. 类加载器ClassLoader:负责加载class文件,不判断它是否能运行,由Execution Engine决定。

  2. Execution Engine执行引擎:负责解释命令,提交操作系统执行。

    new Thread().start(); 执行该方法,有没有启动该线程?

    回答:不确定,因为这个方法的底层实现是交给操作系统启动新线程,不确定操作系统有没有启动成功。

  3. 本地方法栈(Native Method Stack)

用于登记被native标记的java方法。

  1. 本地方法接口(Native Interface)

Java融合C/C++过程中,在内存中专门开辟一块区域处理标记native的代码,当被native标记的java方法被加载本地方法栈(Native Method Stack)中后,Execution Engine执行引擎 加载native libraies

  1. 程序计数器(Program Counter Register)

  2. 方法区(Method Area)

被所有线程共享,所有定义的方法的信息都保存在该区域中,属于共享区间。

存放数据:静态变量+常量+类信息(构造方法/接口定义)+运行时常量池存在方法区中

没有存在数据:实例变量存放在堆内存和方法区无关。

  1. Java栈

队列:先进先出

栈:后进先出

  • statck栈是什么?

栈也叫栈内存,主管J ava程序的运行,在线程创建时创建,线程结束也就释放,对于栈来说不存在垃圾回收机制。生命周期和线程一致,是线程私有的。

存放数据:8种基本类型的变量+对象的引用变量+实例方法都在栈内存中分配。

  • 栈帧中主要保存3类数据

本地变量:输入输出参数及方法内的变量

栈操作:记录出栈,入栈的操作。

栈帧数据:包括类文件,方法等。

  1. 本地方法库

二、堆体系结构

Heap堆(jdk7之前

一个JVM实例只存在一个堆内存,大小可以调节,类加载器读取了类文件之后,需要把类,方法,常变量放到堆内存中,保存所有引用类型的真实信息,方便执行器执行。

新生区

是类的诞生,成长,消亡的区域,一个类在这里产生,最后被垃圾回收。所有的类都在伊甸区被new出来。当伊甸区的内存用完,程序对伊甸区进行垃圾回收,存活对象放置幸存0区,再经过垃圾回收机制放置1区,一区满后,gc()后继续放置0区,依次重复15后,满足条件,就放入养老区。

出现异常java.lang.OutOfMemoryError:java heap space异常,说明java虚拟机的堆内存不够。

原因:java虚拟机堆内存不够,通过-xms,-xmx调整

代码中创建了大量对象,长时间不能被回收。

永久区

常驻内驱区域,存放jdk自身所携带的class interface的元数据,运行环境。此区域不会被垃圾回收到。

jdk1.7;有永久代,常量池1.7在堆。

jdk8:没有永久代,取而代之变成元空间。常量池1.8在元空间。

三、堆参数调优

gc是什么(

分代收集算法)??

  • 次数上频繁收集Young区
  • 次数上较少收集old区
  • 基本不动perm区

4大算法

1、引用计数法

缺点:每次对象赋值时均要维护引用计数器,而计数器本身有所消耗。

较难处理循环引用 jvm不使用该算法。

2、复制算法

年轻代中使用的是minor GC,这种GC算法采用的是复制算法。

  • 没有标记和清除的过程,效率高

  • 没有内存碎片

  • 需要双倍空间

明显缺点:

  1. 浪费了一半的内存。需要两倍的内存空间
  2. 假设100%存活,需要将所有的对象都复制一遍,浪费时间。当存活率比较低时,这种情况可以不用考虑。

3、标记清除

老年代一般是由标记清除或者是标记清理与标记整理的混合实现。

优点:只需要一块内存空间

缺点:需要扫描两次,耗时严重。

会产生内存碎片,内存空间不连续。

4、标记压缩

老年代一般是由标记清除或者是标记清理与标记整理的混合实现。

缺点:效率不高,移动元素需要时间。

5、标记清除压缩

没有最好的算法,只有最合适的算法

年轻代

年轻代的特点是区域相对老年代较小,对象存活率低。

老年代

老年代的特点是区域较大,对象存活率高

posted @ 2020-09-23 20:22  小老弟1999  阅读(301)  评论(0编辑  收藏  举报