欢迎光临散文网 会员登陆 & 注册

黑马程序员JVM完整教程,Java虚拟机快速入门,全程干货不拖沓

2023-03-10 16:18 作者:rickqaq  | 我要投稿








07_栈 P7 - 04:14


 


栈帧过多

栈帧过大


14_线程诊断_cpu占用高 P14 - 03:47





17_堆_定义 P17 - 01:13

垃圾回收





22_方法区_定义 P22 - 01:08


Java虚拟机有一个方法区,是所有Java虚拟之间共享机线程。

方法区域类似于编译代码的存储区域

传统的语言或类似于“文本”段在一个操作系统

的过程。

它存储每个类结构运行时常量池等领域

方法数据和方法和构造函数的代码,包括特别

方法用于类和实例初始化和接口初始化。

方法区上创建虚拟机启动的方法。

虽然方法区逻辑上堆的一部分,简单的实现可以选择不垃圾收集或紧凑。

本规范并不强制的位置的方法

·1.8以前会导致永久代内存溢出

·1.8之后会导致元空间内存溢出



25_方法区_常量池 P25 - 07:35







32_StringTable_intern_1.8 P32 - 00:21





记住new 都是堆内存

永久代回收效率低


直接内存! gc不能 unsafe



垃圾回收

GCROOTs





https://blog.csdn.net/linzhiqiang0316/article/details/88591907


https://blog.csdn.net/weixin_43338519/article/details/107836096

参数配置


并发标记打扫



gc 调优


越大时间也会越长

初始标记:仅仅标记GC ROOTS的直接关联对象,并且世界暂停  

并发标记:使用GC ROOTS TRACING算法,进行跟踪标记,世界不暂停

重新标记,因为之前并发标记,其他用户线程不暂停,可能产生了新垃圾,所以重新标记,世界暂停  


  • 新生代 GC(Minor GC):指发生新生代的的垃圾收集动作,Minor GC 非常频繁,回收速度一般也比较快。
  • 老年代 GC(Major GC/Full GC):指发生在老年代的 GC,出现了 Major GC 经常会伴随至少一次的 Minor GC(并非绝对),Major GC 的速度一般会比 Minor GC 的慢 10 倍以上。



重新标记钱 先清理




02-类文件结构 P97 - 04:24




附加属性_计数;





14-图解运行流程-准备 P109 - 02:09







字节码一样



静态代码>构造方法

父>子


int


22-字节码指令-init P117 - 02:22





23-方法调用 P118 - 03:52



编译类型看左边 运行类型看右边




32-finally-面试题1 P127 - 00:02



跟上例中的finally相比,发现没有athrow了,这告诉我们:如果在finally中出现了 return, 会吞掉异常,可以试一下下面的代码!!!



原来就是把要返回的值先保存到局部变量中,返回前再load到栈中返回

return 不受影响




34-synchronized P129 - 01:50



一开始是new指令在堆上分配了内存并向操作数栈压入了指向这段内存的引用,之后dup指令又备份了一份,那么操作数栈顶就有两个,再后是调用invokespecial #18指令进行初始化,此时会消耗一个引用作为传给构造器的“this”参数,那么还剩下一个引用,会被astore_1指令存储当然new之后有时候会执行<init>,这主要依据字节码中是否包含invokespecial指令。下面主要说一下该指令

主要目的:得到对象存在堆中的地址,这样就可以用当前类,父类,父父类,即继承层的所有对象。  把继承层的所有对象的数据和方法为自己当前对象使用。到局部变量表中。



36-语法糖-自动拆装箱 P131 - 00:38


编译器处理

-127 -128 不会new






40-语法糖-foreach P135 - 01:43


数组:直接fori

集合:迭代器



41-语法糖-switch-string P136 - 05:01


两次switch 防止hash冲突




44-语法糖-twr1 P139 - 00:40


JDKT开始新增了对需要关闭的资源处理的特殊语法try-with-resources:





48-类加载-加载 P143 - 01:53







50-类加载-连接-准备 P145 - 03:32



final直接赋值

cinit 静态成员变量复制 初始化阶段/





51-类加载-连接-解析 P146 - 06:06


将常量池中的符号引用解析为直接引用


字符串->地址


52-类加载-初始化 P147 - 01:04


在类初始化之前的准备阶段,虚拟机会将类变量(static 修饰的变量)分配内存并设置零值。


在类初始化阶段,执行类构造器 <cinit>() 方法。<cinit> 类初始化方法有如下特点:


编译器会在将 .java 文件编译成 .class 文件时,收集所有类初始化代码和 static {} 域的代码,收集在一起成为 <cinit>() 方法;

子类初始化时会首先调用父类的 <cinit>() 方法;

JVM 会保证 <cinit>() 方法的线程安全,保证同一时间只有一个线程执行;



54-类加载-练习2 P149 - 05:15




老师这个静态内部类利用的巧妙,调用Singleton函数,不会触发这个静态内部类的初始化,也就是不会创建这个单例对象



启动类加载路径

默认是使用本来的加载器加载依赖类的

由于JDBC在核心类库中,它由启动类加载器加载,由于驱动是在他的类初始化方法中加载的

于是要显示的调用Classd的forName方法使用一个能加载驱动的加载器加载驱动


1、我来总结下,在jre/lib包下有一个DriverManager,是启动类加载的,但是jdbc的驱动是各个厂商来实现的不在启动类加载路径下,启动类无法加载,而驱动管理需要用到这些驱动


1、SPI机制能够使接口与具体的实现类解耦, 可以根据实际的

业务情况启用或替换具体组件。

2、SPI机制为很多框架的扩展提供了可能。

3、SPI机制更多的是一种思想


3、过程就是:启动类加载器加载DriverManager,DriverManager代码里调用了线程上下文类加载器,这个加载器默认就是使用应用程序类加载器加载类,通过应用程序类加载器加载jdbc驱动


64-运行期优化-逃逸分析 P159 - 07:31




jmm


04-JMM-原子性-问题 P168 - 05:33






05-JMM-可见性-问题 P169 - 00:56


synchronized语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性。但缺点是

synchronized是属于重量级操作,性能相对更低


09-JMM-有序性-理解 P173 - 04:42



对iNSTANCE使用volatile修饰即可,可以禁用指令重排,但要注意在DK5以上的版本的volatile才会真正有效




11-CAS-概述 P175 - 00:43


CAS即Compare and Swap.,它体现的一种乐观锁的思想 与 volatile(易变的)



13-CAS-原子类 P177 - 00:06


乐观锁与悲观锁

CAS是基于乐观锁的思想:最乐观的估计,不怕别的线程来修改共享变量,就算改了也设关系,我吃亏点再重试呗。

synchronized是基于悲观锁的思想:最悲观的估计,得防着其它线程来修改共享变量,我上了锁你们都别想改,我改完了解开锁,你们才有机会。

juc (java.util.concurent)中提供了原子操作类,可以提供线程安全的操作,例如:AtomicInteger、AtomicBoolean等,它们底层就是采用CAS技术+volatile来实现的。



16-synchronized-轻量级锁-无竞争 P180 - 01:37



17-synchronized-轻量级锁-锁膨胀 P181 - 03:44



重量级锁没事,解锁就是




18-synchronized-重量级锁-自旋 P182 - 00:37


自旋成功

自旋失败会放弃




19-synchronized-偏向锁 P183 - 01:22



黑马程序员JVM完整教程,Java虚拟机快速入门,全程干货不拖沓的评论 (共 条)

分享到微博请遵守国家法律