1、JVM的体系结构
2、类加载器和双亲委派机制
1、类加载器包括:虚拟机自带的加载器、启动类(根)加载器、扩展类加载器、应用程序加载器。
2、双亲委派机制:类加载器收到类加载的请求,将这个请求向上委托给父类加载器去完成,直到启动类加载器,启动加载器检查是否能够加载当前类,能加载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载。
顺序: CustomClassLoader(用户自定义类加载器)---->AppClassLoader(系统类加载器)---->ExtClassLoader (标准扩展类加载器)---->BootstrapClassLoader(启动类加载器)
3、native
使用了native,说明java的作用范围达不到了,回去调用底层c语言的库。
进入本地方法栈,调用本地方法本地接口(JNI)。
JNI作用:扩展java的使用,融合不同编程语言为java使用。
4、方法区
静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中,但是实例变量存在堆内存中,和方法区无关。
5、三种JVM
Sun:hotpot
BEA:JRockit
IBM:J9 VM
6、堆和栈(这里不详细说明)
Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。
堆内存分为三个区域:
- 新生区(伊甸园区):Young/New
- 养老区:old
- 永久区:Perm
注:jdk8以后,永久区改名为元空间。
1、新生区
类:诞生和成长的地方,甚至死亡;
伊甸园区:所有的对象都是在此区new出来的;
幸存者区(0,1)
2、养老区
3、永久区
这个区域常驻内存 ,用来存放JDK自身携带的Class对象,Interface元数据,存储的是java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭虚拟机就会释放这个区域的内存。
- jdk1.6之前:永久代,常量池是在方法区;
- jdk1.7: 永久代,去永久代,常量池在堆中;
- jdk1.8之后:无永久代,常量池在元空间。
元空间:逻辑上存在,物理上不存在。
OOM问题:
1、尝试扩大堆内存看结果。参数: -Xms1024m -Xmx1024m -XX:+PrintGCDetails
2、分析内存,看一下哪个地方出现了问题。(专业工具JPofiler)
dump文件参数:-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError
-Xms:设置初始化内存分配大小,默认为1/64。
-Xmx:设置最大分配内存,默认为1/4。
-XX:+PrintGCDetails:打印GC垃圾回收。
-XX:+HeapDumpOnOutOfMemoryError:oom dump。
-XX:MaxTenuringThreshold=15:设定进入老年区时间。
7、GC
分类:轻GC(普通的GC),重GC(全局GC)
1、算法之引用计数法
2、算法之复制算法
优点:没有内存碎片。
缺点:浪费内存空间。
使用场景:对象存活度较低,新生区。
3、算法之标记清除算法
优点:不需要额外的空间。
缺点:浪费时间,会产生内存碎片。
3、算法之标记压缩算法
总结:
内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)
内存整齐度:复制算法=标记压缩算法>标记清除算法
内存利用率:标记压缩算法=标记清除算法>复制算法