JVM
1、什么是JVM
-
J ava V irtual Machine,Java虚拟机
-
JVM是运行在操作 系统之上的,它与硬件没有直接的交互。
2、常见JVM
- Oracle:Hotspot虚拟机(SUN公司研发)
3、执行引擎
-
类似于翻译角色
-
执行引擎负责解释命令(将字节码指令解释编译为机器码指令),提交操作系统执行。
4、类加载器ClassLoader
什么是类加载器
-
作用:负责把class字节码文件加载到jvm里面
-
细节1:class文件在文件开头有特定的文件标识
-
细节2:类加载首先加载类信息(Class),类信息放到方法区里面,创建类实例放到堆里面
类加载器分类
第一种:启动(引导)类加载器:加载使用java.lang java.util等 (jvm自带)
第二种:扩展(平台)类加载器:负责jdk扩展类(jvm自带)
第三种:应用类加载器:负责自己项目(jvm自带)
第四种:自定义类加载器
特别说明
Class class1 = new Demo1().getClass();
ClassLoader classLoader1 = class1.getClassLoader();
System.out.println(classLoader1); //ClassLoaders$AppClassLoader@63947c6b
ClassLoader classLoader2 = classLoader1.getParent(); //ClassLoaders$PlatformClassLoader@776ec8df
System.out.println(classLoader2);
ClassLoader classLoader3 = classLoader2.getParent();
System.out.println(classLoader3); //null
- 注意,这些类加载器本质不是父子关系,只是逻辑上的父子。
双亲委派机制
- 沙箱安全机制
第一步,从下往上,
-
1、当AppClassLoader加载一个class时,首先不会自己去加载,而是把类加载委派给父类加载器PlatformClassLoader去完成。
-
2、当PlatformClassLoader加载一个class时,它首先也不会自己去加载,而是把类加载请求委派给父类加载器BootStrapClassLoader去完成。
第二步,从上往下,
-
3、如果是启动BootStrapClassLoader加载内容,进行加载,之后结束,如果不是启动类加载器加载内容,会用PlatformClassLoader来尝试加载;
-
4、若PlatformClassLoader加载内容,进行加载,之后结束,如果不是启动类加载器加载内容,则会使用AppClassLoader来加载
-
5、如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException
目的:安全性,避免核心类被修改。
5、方法区
方法区放什么
-
类信息
-
常量
-
静态变量
-
常量池
-
jdk7开始,字符串常量池和静态变量放到堆里面(了解)
6、栈
-
栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,每个线程都有自己的栈,它的生命周期是和线程相同的,是线程私有的。
-
栈主要作用用于执行方法的,按照后进先出原则执行,方法之间使用pc寄存器连接(指针)
-
本地方法栈存储方法基本信息(方法名称,参数类型等)
-
虚拟机栈执行方法
-
栈溢出异常:
Exception in thread "main" java.lang.StackOverflowError 通常出现在递归调用时。

7、堆(☆☆☆☆☆)
- 方法区放类信息,堆放实例对象,栈对象引用
堆组成
- 堆逻辑上分为
在jdk1.7及其之前版本,分为新生代、老年代、永久代
在jdk1.8,分为新生代、老年代、元空间
- 新生代分为
新生区分为伊甸园区、幸存0区、幸存1区

堆实例对象过程
1、新创建一个对象,放到堆里面新生区中伊甸区里面
2、当不断创建新的对象,不断放到伊甸区里面,当伊甸区满,执行gc
3、如果gc之后对象还存活状态,进入s0或者s1里面,原则s0或者s1总有一个为空
4、每个对象默认经过15次gc,如果15次gc之后,对象还活着,进入养老区中
5、对象经过15次gc之后还活着,进入养老区里面,如果养老区满了,执行gc
6、养老区满了执行gc,gc之后还是满的状态,抛出oom异常
细节1
新生区执行gc : Minor GC
养老区执行gc: Major GC 和 Full GC
细节2
- 什么情况下,对象进入到养老区中?
第一种情况:对象经过15次gc还存活,进入养老区中
第二种情况:对象伊甸区放不下,直接进入养老区中,如果养老区放不下直接抛出oom异常
细节3
在Java里面可以手动进行垃圾回收,调用System.gc()方法或Runtime.getRuntime().gc()方法可以触发Full GC
堆参数
堆大小调整有相应参数:
-
-Xms表示堆的起始内存,默认是物理电脑内存的1/64。
-
-Xmx表示堆的最大内存,,默认是物理电脑内存的1/4。
- -Xmn 表示新生代堆大小,默认新生代占堆的1/3空间 ,老年代占堆的2/3空间

OOM异常
- 什么情况下,出现堆OOM异常?
情况一:养老区满了,执行gc还满的状态,抛出oom异常
情况二:大对象,伊甸区放不下,养老区也放不下,抛出oom异常
- java.lang.OutOfMemoryError: Java heap space
8、垃圾回收GC
-
Java是自动的垃圾回收(Garbage Collection简称GC)机制。
-
通过垃圾回收器来对不再使用的对象完成自动的回收
-
垃圾回收器主要负责对堆 和 方法区里面的内存进行回收
如何判断对象可以被回收
第一种:引用计数法(不使用了,了解)
第二种:可达性分析算法(使用)
-
可达性分析将对象分为两类:垃圾回收的根对象(GC Root)和普通对象,对象与对象之间存在引用关系
-
将一系列GC Root的集合作为起始点,按照从上至下的方式搜索所有能够被该合集引用到的对象(是否可达),并将其加入到该和集中,这个过程称之为标记(mark),被标记的对象是存活对象。 最终,未被探索到的对象便是死亡的,是可以回收的,标记为垃圾对象。
-
使用可达性分析算法找到可以被回收的对象,要进行垃圾回收,首先进行 Stop-the-World,Stop-the-World停止时间越短越好
-
Stop-the-world意味着 JVM由于要执行GC而停止了应用程序的执行
-
之后进行垃圾回收,使用不同垃圾收集算法进行回收操作
垃圾回收算法
标记清除
-
首先使用可达性算法,找到所有存活对象,进行标记
-
其次遍历这些对象,找到哪些对象没有被标记,回收没有标记对象
-
缺陷:
遍历两次
产生内存碎片
复制算法
-
首先创建大小相同空间
-
其次复制对象到新创建空间里面
-
第三删除原来空间对象
-
新生区s0和s1使用复制算法
标记压缩(整理)
-
首先使用可达性算法,找到所有存活对象,进行标记
-
其次把所有存活对象向一端移动,清除边界以外内存
分代算法
-
新生代使用复制算法,新生代对象存活时间很短
-
老年代使用标记清除和标记压缩,老年代对象存活时候很长,比如连接池里面连接对象
四种引用(面试)
强引用
-
只要对象在使用,不会被回收
-
就算在使用,在特定情况下也会被回收
软引用
在系统要发生内存溢出(OOM)之前进行回收
弱引用
对象只能生存到下一次垃圾收集(GC)之前
虚引用
-
无法获取实例对象,能在这个对象被收集器回收时收到一个系统通知
-
Object类有finalize()方法
这个方法执行gc之前调用这个方法,重写这个方法知道当前对象正在执行垃圾回收操作
任务
-
Java数据类型?
-
Object类有哪些方法和方法作用?
-
Redis支持数据类型有哪些?(大于5种)
-
自我介绍
-
1.JVM是什么? JVM的内存区域分为哪些?
2.什么是OOM ? 什么是StackoverflowError? 有哪些方法分析?
3.JVM 的常用参数调优你知道哪些?
4.GC是什么? GC垃圾收集算法有哪些,算法实现机制
5.什么是类加载器? 类加载器分类?