《Java虚拟机》笔记

2018-04-08  本文已影响0人  GitViolet

记录了自己读《Java虚拟机》的一些笔记,主要在内存管理和代码优化那一块。


1、JVM内存管理

运行时数据区

程序计数器

Java虚拟机栈

本地方法栈

Java堆

方法区

直接内存

对象的创建

对象的内存布局

对象的访问定位

垃圾收集(Garbage Collection,GC)

判断对象是否存活

是否必须回收

回收方法区

垃圾收集算法

标记-清除算法

复制算法
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块

标记-整理算法

分代收集算法
一般是把Java堆
分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代
中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付
出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间
对它进行分配担保,就必须使用“标记—清理”或者“标记—整理”算法来进行回收。

2、JAVA程序编译与代码优化

解析与填充符号表

注解处理器

语义分析与字节码生成

泛型与类型擦除

自动装箱、拆箱与遍历循环

条件编译if(true)

3、高效并发

volatile

原子性、可见性与有序性

原子性(Atomicity):由Java内存模型来直接保证的原子性变量操作包括read、load、assign、use、store和write,我们大致可以认为基本数据类型的访问读写是具备原子性的(例外就是long和double的非原子性协定

可见性(Visibility):可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。

有序性(Ordering):Java内存模型的有序性在前面讲解volatile时也详细地讨论过了,Java程序中天然的有序性可以总结为一句话:如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有的操作都是无序的。前半句是指“线程内表
现为串行的语义”(Within-Thread As-If-Serial Semantics),后半句是指“指令重排序”现象和“工作内存与主内存同步延迟”现象。

先行发生原则
先行发生是Java内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于操作B,其实就是说在发生操作B之前,操作A产生的影响能被操作B观察到,“影响”包括修改了内存中共享变量的值、发送了消息、调用了方法等

实现线程主要有3种方式:使用内核线程实现、使用用户线程实现和使用用户线程加轻量级进程混合实现。

分别是协同式线程调度(Cooperative Threads-Scheduling)和抢占式线程调度(Preemptive Threads-Scheduling)

线程安全当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的

线程安全的实现方法

自旋锁
共享数据的锁定状态只会持续很短的一段时间,为了这段时间去挂起和恢复线程并不值,为了让线程等待,我们只需让线程执行一个忙循环(自旋),这项技术就是所谓的自旋锁

自适应的自旋锁
1.6中引入了自适应的自旋锁。自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定

锁消除
锁消除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。

锁粗化
只在共享数据的实际作用域中才进行同步,这样是为了使得需要同步的操作数量尽可能变小,如果存在锁竞争,那等待锁的线程也能尽快拿到锁。

轻量级锁

偏向锁它的目的是消除数据在无竞争情况下的同步原语,进一步提高程序的运行性能。

上一篇 下一篇

猜你喜欢

热点阅读