思维导图:
1、java->class->classloader->runtime data area->执行引擎,本地方法接口/库。
2、90%的JVM调优都是在对堆进行调优。
3、类装载器的作用:装载class文件,实例化对象后,对象在栈里面,对象内存地址对应的实际属性和方法在堆里面。
加载器执行顺序:根加载器->EXC加载器->应用程序加载器。
4、加载顺序:双亲委派机制
类加载器收到类加载的请求
将这个请求向上委托一直到根加载器
根加载器会检查是否能够加载这个类,如果能加载结束,否则跑出异常通知子加载器进行加载
重复。我们写的大多数的类都是在应用程序加载器加载。
5、沙箱:字节码校验器,确保java文件遵守规范
6、凡是带了native关键字的方法,说明java的作用范围达不到了,需要调用底层C语言的库JNI
7、JNI:扩展java的使用,融合不通的语言为java使用,最初想要融合C和C++
8、JNI在内存区域中专门开辟了一块标记区域,Native Method Stack,登记Native方法,在最终执行的时候,加载本地方法库中的方法。
9、方法区被所有线程共享,所有字段和方法字节码,包括构造函数和接口代码也在此定义,简单说,所有方法的定义都在这里。此区域属于共享区间:静态常量、常量、类信息、运行时常量也存在方法去中,但实例变量存在于堆中。
10、栈内存,主管程序的生命周期和线程同步,线程结束,栈内存就释放了,对于栈来说,不存在垃圾回收的问题。
栈里面放的东西:8大基本类型,对象引用,实例的方法
11、栈运行原理,栈帧 栈如果满了,就会抛出StackOverFlow错误
12、一个JVM只有一个堆内存,堆内存的大小是可以调节的
13、如果出现了OOM错误,如何排查。
定位到代码第几行,使用内存快照分析工具,jprofiler
debug分析代码
使用jprofiler
分析dump内存文件,快速定位内存泄漏
获取堆中的数据
获取大的对象。。。
14、GC垃圾回收
作用区域只有堆和方法区
对象引用计数法:给没个对象分配一个次数,先清理计数少的对象。并不高效,jvm一般不采用。
复制算法:1、每次GC会将伊甸园区活的对象移到幸存区中, 一旦伊甸园区被GC后,他是会空的。2、幸存区,谁空谁是to,在伊甸园区活下来的对象会进入幸存区的to。3、经历15次GC后活下来的对象进入养老区,这个次数可以设置,用于调优。
好处:没有碎片 坏处:浪费了内存空间,对了一半幸存区永远是空的,在极端情况下有弊端。
复制算法的最佳使用场景:对象的存货度较低,适用于新生区。
标记清除算法:
缺点:两次扫描,严重浪费时间,会产生内存碎片。
优点:不需要额外的空间。
标记压缩:在标记清楚的基础上进行移动压缩再清除
各个算法在内存效率、内存整齐度、内存利用率各有优劣,没有最好的算法,只有最合适的算法。
15、JMM JAVA MEMORY MODEL java内存模型