-
jvm的位置:JVM处于操作系统之上,为Java程序在不同的系统平台上的运行提供便利,与硬件没有直接的交互
-
jvm的体系结构 .java->.class->
jvm调优,大部分时间是在调堆 -
类加载器:作用:加载class文件(父->子:boot->ext->app)
-
双亲委派机制:类加载器收到加载类的请求;将此请求委托给父类加载器去完成,一直向上委托,直到启动类加载器(从app开始?向上委托);启动类加载器检查是否能加载当前类,能加载就用当前加载器加载,不能就委派给子加载器
-
lombok自动生成get,set等方法
-
沙箱安全机制:Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。沙箱机制就是将 Java 代码限定在虚拟机(JVM)特定的运行范围中,并且严格限制代码对本地系统资源访问,通过这样的措施来保证对代码的有效隔离,防止对本地系统造成破坏。
沙箱基本组件:字节码校验器(核心类不用校验),类加载器
8…带有native的方法,表示java作用范围达不到了,会调用底层c语言库,这个方法放在本地方法栈中,需要通过调用本地方法接口(JNI:扩展java类的使用,融合不同编程语言为java所使用)来运行
9.程序计数器:用于存放下一条指令所在单元的地址的地方。线程私有
10.方法区:static final 静态变量,常量,类信息(构造方法,接口定义),运行时的常量池放在方法区中。
实例变量存在堆中
11.线程结束,栈内存就释放,栈不存在垃圾回收问题
12.栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。
函数的每次调用,都有它自己独立的栈帧。栈帧中维持着函数调用所需要的各种信息,包括函数的入参、函数的局部变量、函数执行完成后下一步要执行的指令地址、寄存器信息等。
13.java对象实例化过程
https://www.cnblogs.com/flyer-ovo/p/16070030.html
14.堆内存
GC垃圾回收机制:主要针对伊甸园区和老年区。jdk8以后,永久区改名为元空间。
1>新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden Space)和幸存者区(Survivor Space),所有的类都是在伊甸区被new出来的。幸存区有两个:0区和1区(0区和1区是会发生交换的)。
当伊甸区的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸区进行垃圾回收 (轻量级垃圾回收即Minor GC),将伊甸区中的不再被其他对象所引用的对象进行销毁,然后将伊甸区中的剩余对象移动到幸存0区。
若幸存0区也满了,再对该区进行垃圾回收,移动到1区。
如果1区也满了呢?再对该区进行垃圾回收,移动到养老区,默认要经历15次Minor GC,才能进行养老区,大多数对象全都在新生区就被回收掉了。
若养老区也满了,那么这个时候将产生重量级垃圾回收(也即Full GC),进行养老区的内存清理。
若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常(也即OutOfMemoryError,内存溢出错误)。
2>老年区
老年区主要存放JVM认为生命周期比较长的对象(经过几次的Young Gen的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁。
3>永久区
这个区域是常驻内存的,用来存放JDK自身携带的Class对象、Interface元数据,存储的是Java运行时的一些环境或类信息,这个区域不存在垃圾回收,关闭VM就会释放这个区域的内存。
永久区出现OOM的情况,①一个启动类,加载了大量的第三方jar包;②Tomcat部署了太多的应用,大量动态生成反射类
15.堆内存满了会OOM:解决方法:1)尝试扩大堆内存,2)分析问题出在哪。
a.能够看到代码第几行出错:内存快照分析工具:MAT,JProfiler
b.debug一行行分析代码
MAT,JProfiler作用:1)分析内存dump文件,快速定位内存泄露。2)获得堆中数据 3)获得大对象
305664K(新生区) + 699392K(老年区) = 1005056K = 981.5M,还没有加元空间的内存,就已经等于总的了,所以元空间物理上不存在于jvm中,元空间实际上存在于本地内存。这意味着不会再java.lang.OutOfMemoryError: PermGen问题,也不再需要你进行调优及监控内存空间的使用。
元空间与方法区之间的关系是:元空间就是方法区的一个具体实现,而方法区就是一个接口。
新生区中的伊甸区、幸存0区以及幸存1区的比例是8:1:1。
16.-Xms参数与-Xmx参数分别是设置JVM的堆内存的初始大小和最大大小,HeapDumpOnOutOfMemoryError表示在内存错误时打印dump文件,可以再jprofiler中打开,从而快速定位错误位置
17.GC:jvm在进行GC的时候,并不是对三个区域统一回收,大部分时候,回收的都是新生代。
两种类型:轻(普通)GC,重(全局)GC
18.GC算法
复制算法(主要是年轻代使用,即对象存活率较低):GC复制算法的思路是将堆一分为二。申请内存时,我们统一在A堆分配,当A堆用完了,我们将A堆中的活动对象全部复制到B堆,然后A堆的对象就可以全部回收了。这时我们不需要将B堆的对象又搬回A堆,只需要将A和B互换以下就行了,这样原来的A堆变成B堆,原来的B堆变成了A堆。GC复制算法就是在两个堆之间来回倒腾。
每次GC都会将伊甸园活的对象放到幸存区,保证伊甸园是空的,幸存区1,0也叫from to,是动态变化的,谁空谁是to。一个对象如果15次(可以在jvm调优)GC还不空,就放到老年代。
GC复制算法的优点:
吞吐量优秀。这得益于GC复制算法只会搜索复制活动对象,能在较短时间内完成GC,而且时间与堆的大小无关,只与活动对象数成正比。相比于需要搜索整个堆的GC标记清除算法,GC复制算法吞吐量更高,而且堆越大,差距越明显。
不会发生碎片化。因为每次复制都会执行压缩。
GC复制算法的缺点也是相当明显:
堆的使用效率低:要留一半的空间用来复制,所以堆的利用率总小于50%。
复制时存在递归调用,需要消耗栈空间,并可能导致栈溢出。
19.GC标记清除算法:清除算法由标记阶段和清除阶段构成,在标记阶段会把所有的活动对象都做上标记,然后在清除阶段会把没有标记的对象,也就是非活动对象回收。
优点:不需要额外空间
缺点:两次扫描浪费时间,会产生内存碎片
20.GC标记压缩算法:先标记,再清除,最后压缩。防止内存碎片。也可以先标记清除几次,在压缩。(只有前两步是标记清除)
总结:(GC:分代收集算法)
内存效率:复制>标记清楚>标记压缩(时间复杂度)
内存整齐度:复制=标记压缩>标记清除
内存利用率:标记压缩=标记清除>复制
21.JMM