1.jvm的位置
2.jvm体系结构
3.类加载器
作用:就是加载 class 文件
1.虚拟机额自带的加载器
2.启动类(根)的加载器
3.扩展类加载的加载器
4.应用程序的加载器
1,类加载器收到类加载的请求
2,将这个请求向上委托给父加载器去完成,一致向上委托,知道启动类加载器
3,启动类加载器检查是否能够加载当前这个类,能加载就结束,使用当前的加载器,否则抛出异常,通知子加载器进行加载
4,重复步骤3
5,null java调用不到 ,-----c 或者 c++
双亲委派机制:安全
介绍:如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行;
如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器;
如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式
4.Native 方法区 pc寄存器
**Native关键字:**凡是带了native关键字的,说明java的范围达不到了,获取调用c语言的库
然后会进入本地方法栈调用本地方法,“本地接口(JNI: JAVA NATIVE INTERFACE”) ;
**JNI作用:**扩展java的应用,融合不同编程语言为java所用,最初是c , c++
并且他的内存区域中专门开辟了一块标记区域,NATIVE METHOD STACK,登记native方法
在最终执行的时候,加载本地方法库中的方法通过JNI
**pc寄存器:**程序计数器:Programe Count Register
概念:每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区的方法字节码(用来存储指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎忽略不计。
方法区: method area
概念:方法区是所有线程共享的,所有字段和方法字节码,以及一些特殊方法,例如构造函数,接口代码也在此定义,简单说,所有定义方法的信息,都保存在该区域,此区域属于共享区间
必须知道
静态变量,常量,类信息(构造方法,接口定义),运行时的常量池存在方法区中,但是实例变量存在堆内存张,和方法区无关(static , final, Class ,常量池)
5.栈
程序=数据结构+算法
**概念:**栈内存,主管程序的运行,生命周期和线程同步;线程结束,栈内存也就是释放对于栈来说
不存在垃圾回收问题
一旦线程结束,栈就over
**特点:**先进后出
**栈的存储:**8大基本数据类型+对象引用+实例的方法
6.堆(Heap)
三种jvm(了解)
1,sun公司的HotSpot(我们学习的就i是这个)
2,BEA 公司的JRockIt
3,BM公司的J9 Vm
**堆的概念:**一个jvm只有一个 堆内存,堆内存的大小是可以调节的。
类加载器读取了类文件之后,一般会把什么东西放入到堆中?
**答:**实体类的方法,属性,变量,保存我们引用类型的真实对象
堆内存大致分为三个区域
(新生区)伊甸区(young/new)
养老区(old)
永久区(Perm)
堆内存大致结构
GC垃圾回收,主要在伊甸园区和养老区
假如对堆内存满了,OOM,报错是,java.lang.outOfMemoryError:java Heap space
另外,在JDK1.8之后,永久存储区改了名字 叫元空间
新生区
- 类:诞生和成长的地方,甚至死亡。
- 伊甸园,所有对象都在伊甸园区被new出来的
- 幸存者区(0,1)
经过研究99%的对象都是临时的
永久区
**概念:**这个区域是常驻内存的,用来存放JDK本身携带了的CLass对象,Interface元数据,存储的是java运行时的·一些环境或者类信息,这个区域不存在垃圾回收,关闭VM虚拟机就会释放这个区域的内存
一个启动类,加载了大量的第三方的jar包,Tomcat部署了太多的应用,大量动态生成的反射类,不断地被加载,直到内存满了,就会出现OOM(堆内存溢出)
永久区在不同版本的差别
- jdk1.6之前:名称为永久代,常量池在方法区
- jdk1.7 :名称叫永久代,但是慢慢退化了,(开始了“去永久代”)
,常量池在堆中
jdk1.8 : 没用了永久代,常量池 在元空间。
元空间:逻辑上存在,实际上不存在。
如果遇到了OOM应当如何处理?
**答:1,尝试扩大堆内存看结果
2,分析内存看一下那个地方出现了问题(使用专业的工具)
调节堆内存的参数
:-Xms8m -Xmx8m -XX:+PrintGCDetails(这句设置中的数字8 代表8m)
-Xms8m:设置初始化内存分配大小 默认为 1/64
-Xmx8m:设置最大初始化内存 默认为 1/4
-XX:+PrintGCDetails:打印GC详细信息
-XX:+HeapDumpOnOutOfMemoryError (OOM dump)
测试代码
import java.util.Random;
public class Oom {
public static void main(String[] args) {
String guo="liangxi";
//测试OOM堆内存溢出 并进行JVM调优
while(true){
guo+=guo+new Random().nextInt(888888888)+new Random().nextInt(999999999);
}
}
}
堆内存异常信息(OOM)
**jvm在进行GC时,并不是对这三个区域统一回收,大部分时候,回收都是新生代
- 新生代
- 幸存区(from to)
- 老年区
GC有两种类
- 轻GC(普通的GC)
- 重GC(全局GC)**
7.GC介绍之引用计数法
常见的GC算法:标记清除法,引用计数法,复制算法,标记压缩
使用引用计数法来进行垃圾回收,本身也有消耗**
8.GC介绍之复制算法
优点:没有内存碎片
缺点:浪费了内存空间(假设对象100%存活,对了一半空间永远是 空to)
复制算法最佳使用场景:对象存活度最低的时候,----新生区
from 和 to 在不断的调动
9.GC介绍之标记压缩清除算法
标记清除算法
优点:不需要额外的空间
缺点:两次扫描,严重浪费时间,会产生内存碎片
标记压缩算法
10.GC算法总结
**内存效率:**复制算法 > 标记清除算法 >标记压缩算法(时间复杂度)
**内存整齐度:**复制算法 = 标记压缩算法 > 标记清除算法
**内存利用率:**标记清除算法 = 标记压缩算法 > 复制算法
年轻代
- 存活率低
- 复制算法
老年代
- 区域大:存活率
- 标记清除(内存碎片不是太多)+标记压缩混合实现