脚本宝典收集整理的这篇文章主要介绍了JAVA虚拟机,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
正式为类变量分配内存并设置类变量初始值,都将在方法区中进行分配
虚拟机将符号引用替换为直接引用的过程
<clinIT>
<init>
六种触发初始化的情形如下:
对应方法的重载:依赖静态类型来定位方法执行的版本,属于多分派
对应方法重写,属于单分派。
确认方法的步骤:
几个相关名词的定义:
宗量:方法接受者与方法的参数 单分派:根据一个总量对目标方法进行选择 多分派:根据多个宗量对目标方法进行选择
JAVA语言是一门静态多分派 动态单分派语言
自旋:自旋是指某线程需要获取锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取锁。
引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级锁执行路径,因为轻量级锁的获取及释放依赖多次CAS原子指令,而偏向锁只需要在置换ThreadID的时候依赖一次CAS原子指令。 当只有一个线程去竞争锁的时候,我们不需要阻塞,也不需要自旋,因为只有一个线程在竞争,我们只要去判断该偏向锁中的ThreadID是否为当前线程即可。如果是就执行同步代码,不是就尝试使用CAS修改ThreadID,修改成功执行同步代码,不成功就将偏向锁升级成轻量锁。
获取轻量锁的过程与偏向锁不同,竞争锁的线程首先需要拷贝对象头中的Mark Word到帧栈的锁记录中。拷贝成功后使用CAS操作尝试将对象的Mark Word更新为指向当前线程的指针。如果这个更新动作成功了,那么这个线程就拥有了该对象的锁。如果更新失败,那么意味着有多个线程在竞争。 当竞争线程尝试占用轻量级锁失败多次之后(使用自旋)轻量级锁就会膨胀为重量级锁,重量级线程指针指向竞争线程,竞争线程也会阻塞,等待轻量级线程释放锁后唤醒他。
重量级锁的加锁、解锁过程和轻量级锁差不多,区别是:竞争失败后,线程阻塞,释放锁后,唤醒阻塞的线程,不使用自旋锁,不会那么消耗CPU,所以重量级锁适合用在同步块执行时间长的情况下
ReentrantLock扩展了synchronized ReentrantLock可以对锁的等待事件进行设置,这样就避免了死锁 ReentrantLock可以获取各种锁的信息 ReentrantLock可以灵活地实现多路通知
两者加锁机制不一样: ReentrantLock底层调用的是Unsafe的park方法加锁 synchronized操作对象头中的mark word信息进行加锁
类加载器分类:每一个类加载器都有一个独立的名命空间
启动类加载器:是虚拟机自身的一部分,用来加载JAVA_HOME/lib/目录中的类 扩展类加载器:负责加载java.ext.dirs系统变量指定的路径中所有的类库 应用程序类加载器:负责加载用户类路径上的指定类库,默认使用的类加载器
如果一个类加载器收到了类加载的请求,它首先不会去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的加载器都是如此,这样所有的加载请求会被传到顶层的启动类加载器中,只有当父类加载无法完成加载请求时,子加载器才会尝试去加载类
引用计数法:当有一个地方使用计数值+1,失效时-1,为0时是不可再被引用的对象 缺点:循环引用时,某些对象将无法被回收掉
可达性分析算法:通过一系列的称为GCROOTS的对象作为起点,往下搜索(路径为引用链),当对象不与GC任何引用链相连时,则这些对象是不可达的。 GCROOTS对象包括:
垃圾收集算法:
垃圾收集器: ParNew(多线程 高吞吐)
CMS(初始标记,并发标记(时间长),重新标记,并发清除(时间长)低延迟)
G1(将整个堆划分为一个个小块,1-32M,RememberSet指向块的内存地址) 调整小 -XX:InitiatingHeapOccupancyPErcent=45% 增多Minor GC频率,减少Full GC频率
参考文献 ^1 周志明 《深入理解JAVA虚拟机》 第二版 TIPS: 转载必须注明原文地址 和 引用参考文献部分
以上是脚本宝典为你收集整理的JAVA虚拟机全部内容,希望文章能够帮你解决JAVA虚拟机所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。