双亲委派机制为何可以防止核心API被篡改?
因为每个类加载器都只会去加载指定目录下的包,即使自己定义了java.lang.String的类,加载该类时类加载器会委托父类加载器加载,最终到引导类加载器,引导类加载器只加载lib目录下面的类。
ㅤ
关于栈帧中的动态链接问题
这里涉及到方法的调用
方法的调用:
在Jvm中,将符号引用转换位调用方法的直接引用,与方法的绑定机制相关。
静态链接:
当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译期可知,且运行期保持不变。
将调用方法的符号引用转换为直接引用的过程称为静态链接。
动态链接:
被调用的目标方法在编译期无法被确定下来,只能够在程序运行期将方法的符号引用转换为直接引用,这种引用转换的过程具备动态性,称为动态链接。
方法的绑定机制分为早期绑定(Early Binding)和晚期绑定(Late Bingind)。绑定是一个字段、方法或类在符号引用被替换为直接引用的过程。
早期绑定:
被调用的目标方法在编译期可知,且运行保持不变。
晚期绑定:
被调用方法在编译期无法被确定下来,只能够在程序运行期根据实际类型绑定相关的方法。
参考https://blog.youkuaiyun.com/qq_20394285/article/details/104673913
ㅤ
方法返回地址
无论通过哪种方式退出,在方法退出后到该方法被调用的位置,方法正常退出时,调用者的PC计数器的值作为返回地址,即调用该方法的指令的下一条指令地址,而通过异常退出的,返回地址是要通过异常表来确定,栈帧中一般不会保存这部分信息。
ㅤ
关于虚方法和非虚方法,虚方法表
虚方法就是编译阶段无法确定的方法,只有在运行期才能确定的方法。比如调用接口的某个方法,实际调用的是接口实现的方法。
虚方法表是在链接阶段生成的,在类变量初始值完成之后。虚方法表存储了每个方法的实际入口。
ㅤ
Young GC、old gc、full GC触发时机
Young GC
新生代Eden满
ㅤ
old gc
young gc后老年代空间不足,此时进行full gc,full gc会触发old gc
cms、G1老年代占用比例达到阈值
ㅤ
full GC
system.gc
元空间满
老年代满
Eden、from区转to区(young gc正在进行),由于to区不足对象直接晋升老年代,此时老年代也不足
在young gc之前(young gc还未进行)检查老年代连续空间小于历次晋升的平均大小,直接full gc(jdk6之后HandlePromotionFailure默认为true,无法修改,jdk6之前可以设置HandlePromotionFailure,如果设置为false,在young gc之前,老年代连续空间小于新生代对象总大小就会直接full gc,没有后面的平均大小的判断)。这里补充一句:cms和G1收集器很难出现full gc的原因是这两个回收器的老年代在达到阈值后就会触发垃圾回收,不用等到老年代满。
ㅤ
逃逸分析、标量替换、栈上分配
是在JIT即使编译器优化后的结果。在字节码层面无法观察到。
ㅤ
方法区包括
类信息
- 域信息
- 方法信息
- 静态变量
运行时常量池
jit代码缓存
ㅤ
static final的常量说明
假如static final修饰的常量在编译阶段值就能确定。那么当其它类引用该变量时就不需要加载该类。如果该类被初始化,则static final修饰的常量赋值是在链接的准备阶段。
ㅤ
finalize是否一定会执行
如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列之中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的情况),将很可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。
ㅤ
三色标记与读写屏障,多标,漏标,增量更新,原始快照
参考https://www.jianshu.com/p/12544c0ad5c1
参考https://blog.youkuaiyun.com/qq_34687559/article/details/105795213
ㅤ
垃圾回收器
CMS
初始标记->并发标记->再次标记->并发清理
初始标记:标记GC Roots能直接关联到的对象
并发标记:遍历整个GC Roots对象图
再次标记:修正并发标记的改动,其中涉及了漏标,多标,新建对象处理等问题
并发清理:该阶段涉及到2个问题。一个是该阶段如果对象变成垃圾,那么这些垃圾必需等到下次才能清理;另一个是新建的对象会不会误删,答案是不会的,新建的对象会放在一个特点的区域,该区域在本垃圾回收不会被清理。
ㅤ
G1
young GC->young GC+并发标记->混合回收
young GC
使用了复制算法,先是标记GC Roots能直接关联到的对象,这里还涉及到Remember Set里面的引用。遍历整个GC Roots,使用复制算法,将Eden,from区转移到to区,from区中年龄超过阈值的会转移到老年代。
标记阶段
达到阈值后触发开始标记,整个过程和CMS的垃圾回收过程差不多。
区别:
并发标记:该阶段可能被young gc中断,如果发现整个区域都是垃圾,则直接回收该区域,并且会记录区域对象的存活比例。
清理阶段
- 分独占清理阶段:只是计算出每个区域的对象存活比例,识别可回收的区域,为后面的并发清理阶段做铺垫,此阶段不进行垃圾回收
- 并发清理阶段:该阶段其实也是处在混合回收阶段
混合回收
混合回收包括新生代和老年代的回收,老年代的回收就是上述的并发清理阶段。其中老年代只回收部分区域,且回收的区域分多次进行(默认8),每次回收都是STW的。
G1 GC也会存在Full GC问题。原因和CMS一样,都是因为会出现在并发清理阶段再次出现老年代空间不足的情况。
ㅤ
吞吐量和停顿时间
在ParNew 和Parallel Scavenge两款收集器中,前者注重停顿时间,而后者注重吞吐量。那后者是怎么来增加吞吐量的呢?可以增加新生代的内存大小,这样就能减少垃圾回收的次数,但这样每次回收的时间会增多。如果想减少单次垃圾回收的停顿时间,那么可以减小新生代的内存大小。
ㅤ
双亲委托模型的弊端以及线程上下文类加载器详解
父类加载器通过一个上下文类加载器查看到子类加载器加载的类
参考https://www.jianshu.com/p/09f73af48a98
ㅤ
关于双亲委派机制的上下文类加载器问题
tomcat类加载器及jvm类加载器的原理,解决上面的问题
参考https://www.cnblogs.com/aspirant/p/8991830.html
ㅤ
使用压缩指针java内存不能超过32g,否则压缩指针失效
参考https://blog.youkuaiyun.com/liujianyangbj/article/details/108049482
ㅤ
java对象头的大小,不同位的操作系统以及是否使用压缩指针
1.在32位系统下,存放Class指针的空间大小是4字节,MarkWord是4字节,对象头为8字节。
-
在64位系统下,存放Class指针的空间大小是8字节,MarkWord是8字节,对象头为16字节。
-
在64位开启指针压缩的情况下 -XX:+UseCompressedOops,存放Class指针的空间大小是4字节,MarkWord是8字节,对象头为12字节。
-
如果对象是数组,那么额外增加4个字节