1、类加载器分类
1、引导类加载器,负责加载支撑Jre/lib目录下的核心类库
2、扩展类加载器:负责加载Jre/lib目录下的ext扩展类jar包
3、应用程序类加载器:负责加载classpath下的类包
4、自定义类加载器:负责加载用户自定义路径下的类包
2、jvm内存模型(运行时数据区)
1、程序技术器
2、java虚拟机栈(字节码级别)
用于描述java方法执行的线程内存模型,每个方法被执行的时候,jvm都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个java方法执行完毕,这个栈帧就是在jvm中从入栈到出栈的过程。
这里会诞生两种异常状况:
1、如果线程请求的栈深度大于虚拟机允许的深度,将抛出StackOverflow异常。
2、如果Jvm容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常。
局部变量表:编译期的基础数据类型、对象引用、returnAddress
3、本地方法栈(用于Natvie修饰的方法)
和java虚拟机栈发挥作用非常相似,区别在于java虚拟机栈只是针对字节码服务,而本地方法栈则是用到本地Native方法服务。
java如果需要调用其他语言解释方法的时候,则可以通过Natvie告知编译器应该需要使用其他语言解释。
4、java堆(多个线程直接共享区域)
所有对象实例和数据都应该在堆上分配(垃圾收集器内存:新生代、老年代、永久代、Eden空间、From Survior空间、To Survivor空间等),多个线程直接共享区域
-Xmx和-Xms
如果在Java堆中没有内存完成实例分配、并且堆也无法再扩展时,会抛出OutOfMemoryError异常。
5、方法区 (多个线程直接共享区域)
用于储存类型信息、常量、静态变量、即时编译器编译之后的代码缓存等数据,(永久代内存管理)
-XX:MaxPermSize
如果方法区无法满足新的内存分配,将抛出OutOfMemoryError异常。
6、运行时常量池
实际上也是方法区的一部分,用于存储编译期生成类的字面量与符号引用,可以管理运行期的常量内存(运行时常量池)
受方法区的影响, 如果方法区无法满足新的内存分配,将抛出OutOfMemoryError异常。
3、直接内存(非运行时数据区)
使用Native来分配堆外内存,不受java堆大小限制,但会受本机总内存限制(物理内存、SWAP分区和分页文件),通过java堆里面的DirectByteBuffer对象操作NIO的channel与缓冲区的I/O方式。可以提高显著提高通道和缓冲区的读写性能,但是分配回收的需要更大的代价。
如果直接内存无法满足新的内存分配,将抛出OutOfMemoryError异常。
5、分代收集机制:(堆内存模型)
新生代:(Eden From(S1) To(S2))
Major GC/Old GC
老年代(Tenured)
Full GC
收集整个Java堆/方法区。
垃圾收集过程:
Minor GC/Yong GC过程
1、收集GC root可达对象,分配到Eden区,
2、当Eden区满了情况下,将Eden中GC root可达的对象通过标记复制法复制到From区(S0),同时通过标记清除法清除Eden区。
3、当From区(S0)满了的情况下,将From区依旧被GC root可达的对象复制到To区(S1)区,
同时标记清除To区。
4、当To区满了情况下,To区被GC root可到的对象复制到From区,同时标记清除To区。
5、对于躲过一次Minor GC的GC root可达的对象,使用引用计数+1,当引用次数达到15之后,进入老年代收集
Major GC/Old GC
当老年代区域满了的情况下,不会使用标记复制方法,而是使用标记整理法,即将GC root可达的对象向内存空空间一端移动,然后使用标记清除法清除掉边界以外的内存。
这样的好处是,不用像minc gc 使用s1区和s2区,可以直接节约掉50%空间,而且不会频繁出现复制操作,效率更好。
6、对象回收
1、引用计数法:在对象中添加一个引用计数器,如果有一个地方引用这个对象,计数+1,当引用失效,计数-1,当对象的计数器为0的时候,回收对象。
2、可达性分析法:
从GC Roots开始,向下搜索引用,没有任何引用链的情况下,证明GC Root不可达到这个对象,回收对象。
可作为GC Roots对象
1、java虚拟机栈中引用的对象,包括参数、局部变量、临时变量
2、方法区中的静态变量、常量引用
3、JNI、native引用
4、java虚拟机内部的引用,基础数据类型包装对象引用、异常对象、系统类加载器
5、sunchronized关键字持有的对象。
强引用关系存在永远不会被回收。new
A a = new Aclass();
a=null;
a之后不能再被引用,jvm会回收。
软引用关系会在发生内存溢出之前进行两次回收,如果还没有足够的内存,内存还是会溢出的。SoftReference,可实现缓存。
弱引用关系对象,不管内存够不够,都会被回收掉。WeakReference。
虚引用,该引用无法获取一个对象的实例,只是为了能在这个对象被回收时收到一个系统通知。PhantomRefrence
7、垃圾收集器
1、清除算法
2、复制算法
3、整理算法
8、垃圾收集器
新生代收集器:Serial ParNew Parallel Scavenge
老年代收集器:Serial Old CMS Parallel Old
堆内存垃圾收集器:G1(Garbage First)
CMS :并发收集器,基于标记-清除法实现的,
1、初始标记:只是标记一下GC root 直接关联的对象,会发生停顿。
2、并发标记:垃圾回收线程会遍历和GC root关联所有可达对象,和用户线程是直接并发执行的,因此不会停顿用户线程的。
3、重新标记:并发情况下,会发生用户线程执行而导致并发标记发生变动的记录,更新标记记录,会发生停顿并且会比初始标记时间更长。
4、并发清除:垃圾回收线程会清除标记清除GC root不可达的对象,可以和用户线程并发执行。
缺点:碎片化内存比较严重,必须预留一定的老年代内存空间来分配内存,不能等待占用100%的情况下才触发回收,如果预留的空间不足以满足用户分配的空间,将会触发一次并发失败,此时将会冻结用户线程,临时启用Serial Old重新收集老年代线程,这样停顿时间会非常严重
-XX:CMSInitiatingOccu-pancyFraction可以设置预留空间,慎重。需要生产反复设计