深入理解Java虚拟机--读书笔记3/3

Chap 10 早期(编译期)优化
1.编译过程:
A.解析与填充符号表。
B.插入式注解处理器的注解处理过程。
C.分析与字节码生成过程。
2.解析包括词法分析(将代码中的字符流转变为标记的集合Token)和语法分析(将Token序列构造成抽象语法树AST的过程)。
3.注解处理器用于实现对注解Annotation的支持。
4.clinit类初始化和linit实例初始化就是在字节码生成过程中生成的。
5.Java与语法糖之泛型与类型擦除:Java中的泛型只存在于程序源码中,在编译后的字节码中,就已经替换成了原来的原生类型并进行了强制转换。这称之泛型擦除。
PS:当泛型遇到重载,void method(<List<String>> list)和void method(<List<int>> list)不能编译通过,但是可以更改返回类型完成“重载”。
6.Java使用if语句实现条件编译:if(true)…

Chap 11 晚期(运行期)优化
1.HotSpot虚拟机中内置两个即时编译器,分别为Client Compiler和Server Compiler。可以使用-client和-server参数强制指定虚拟机的模式。

Chap 12 Java内存模型与线程
1.Java内存模型规定所有的变量都存储在主内存,每个线程还有自己的工作内存,工作内存保存了线程使用到的变量的在主内存的副本。线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,而不能直接读写主内存中的变量。不同线程不能访问不同线程的工作内存,线程间变量值的传递均需要通过主内存来完成。
2.内存间交互操作包括lock/unlock,read读取/load载入,use使用,assign赋值,store存储/write写入,这些操作都是原子性的。
3.volatile类型变量(最轻量级的同步机制)的特殊规则:
A.volatile保证该变量对于所有线程的可见性(普通变量需要将值同步到主内存后其他线程才能看到)。但是volatile并不能保证变量线程安全,比如++操作会编译为多条指令,多条指令间可能会有其他线程的执行执行。正确的volitile使用法法是:
while(!volitile_var){…}
B.volatile变量的第二个语义是禁止指令重排序优化。普通变量不保证变量赋值操作的顺序与代码中的顺序一样。
4.对于long和double的特殊处理:java允许备用油被volatile修饰的long和double这种64为的数据类型分两次32位操作完成。但是多数虚拟机都保证了这两个操作的原子性。
5.Java线程的实现方式:内核线程实现、用户线程实现和用户线程加轻量级进程混合实现。
6.Java线程调度分为协同式调度和抢占式调度。

Chap 13 线程安全与锁优化
1.Java语言中的线程安全分为:
A.不可变:final修饰的变量,绝对安全。
B.绝对线程安全:不需要任何额外的同步措施就能保持安全。
C.相对线程安全:单个操作访问时安全的(synchronized修饰),但是访问顺序会影响线程安全。如Vector。
D.线程兼容:对象本身不是线程安全的,但是可以通过正确的同步方法实现线程安全。如HashMap、ArrayList。
E.线程对立:无论如何同步,都不能实现线程安全,比如Thread的suspend()和resume()方法。
2.线程安全的实现方法:
A.互斥同步:使用synchronized关键字。synchronized对于同一线程是可以重入的。还可以使用ReentrantLock实现同步。
B.非阻塞同步:依赖于硬件,如AtomicInteger。悲观锁:只要不做同步就会出现问题,无论竞争是否出现都要加锁。乐观锁:先操作,如果冲突就做补偿措施,例如不断重试。
C.无同步方案:可重入代码和线程本地存储。
3.JVM锁优化技术:
A.自旋锁(线程忙循环来避免频繁进行线程的切换)与自适应锁(自旋的时间不再固定,动态决定)。
B.锁消除:虚拟机编译时对不可能存在数据竞争的锁进行消除。
C.锁粗化:对于频繁调用加锁的语句,JVM生成代码时更大范围内的加锁。
D.轻量级锁
E.偏向锁

    原文作者:java虚拟机
    原文地址: https://blog.csdn.net/conanswp/article/details/69654303
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞