首页  

JVM知识点汇总     所属分类 jvm 浏览量 550
运行时数据区 

程序计数器
Java 虚拟机栈
本地方法栈
Java 堆
方法区
运行时常量池
直接内存

每个线程都需要一个独立的程序计数器
 

如何判断对象是否可回收 引用计数法 根搜索算法 GC Roots 引用链(Reference Chain)
4种引用 强引用 Strong Reference 软引用 Soft Reference 弱引用 Weak Reference 虚引用 Phantom Reference
垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 内存分配原则 对象优先分配在 Eden 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保
Class文件 二进制流 头4个字节 魔数 Magic Number Magic Number version constant pool access flags this class name super class name interfaces fields methods attributes
类加载器 启动类加载器(Bootstrap ClassLoader) 使用C++实现(仅限于HotSpot),是虚拟机自身的一部分 负责将存放在\lib目录中的类库加载到虚拟机中 ,其无法被Java程序直接引用 扩展类加载器(Extention ClassLoader) 由ExtClassLoader实现,负责加载\lib\ext目录中的所有类库,开发者可以直接使用 应用程序类加载器(Application ClassLoader) 由AppClassLoader实现 ,负责加载用户类路径(ClassPath)上所指定的类库 双亲委派模型(Parents Delegation Model) java.lang.Object,在 rt.jar 中 委派给启动类加载器进行加载,因此Object类在各个类加载器环境中,都是同一个类 类加载过程 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型
虚拟机和物理机 物理机的执行引擎是直接建立在处理器、硬件、指令集和操作系统层面的。 虚拟机的执行引擎是自己实现的,因此可以自行制定指令集和执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式 运行时栈帧结构 栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构, 存储了方法的 局部变量表 操作数栈 动态连接 方法返回地址 Java的方法调用 Class文件的编译过程不包含传统编译的连接步骤, 一切方法调用在Class文件里面存储的都只是符号引用,而不是方法在实际运行时内存布局中的入口地址。 这使得Java有强大的动态扩展能力,但使Java方法的调用过程变得相对复杂, 需要在类加载期间甚至到运行时才能确定目标方法的直接引用。 Java虚拟机调用字节码指令 invokestatic 调用静态方法 invokespecial 调用实例构造器方法、私有方法和父类方法 invokevirtual 调用所有的虚方法 invokeinterface 调用接口方法 解释执行(通过解释器执行)编译执行(通过即时编译器产生本地代码) 基于栈的指令集和基于寄存器的指令集
Javac编译过程 解析与填充符号表 插入式注解处理器的注解处理 分析与字节码生成 即时编译器 Just In Time Compiler,JIT编译器 热点代码 被多次调用的方法 被多次执行的循环体 分层编译 第0层 程序解释执行,解释器不开启性能监控功能,可触发第1层编译。 第1层 C1编译,将字节码编译为本地代码,进行简单可靠的优化,如有必要加入性能监控的逻辑 第2层 C2编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。 Client Compiler 和 Server Compiler 同时工作 Client Compiler 更高的编译速度, Server Compiler 更好的编译质量 热点探测 基于采样的热点探测,虚拟机周期性检查各个线程的栈顶,如果发现某个方法经常出现在栈顶,那这个方法就是“热点方法”。实现简单高效,但是很难精确确认一个方法的热度。 基于计数器的热点探测,虚拟机会为每个方法建立计数器,统计方法的执行次数,如果执行次数超过一定的阈值,就认为它是热点方法。 HotSpot虚拟机使用第二种,有两个计数器 方法调用计数器 回边计数器(判断循环代码) 方法调用计数器统计方法 经典的优化技术(即时编译器) 语言无关的经典优化技术之一 公共子表达式消除 语言相关的经典优化技术之一 数组范围检查消除 最重要的优化技术之一 方法内联 最前沿的优化技术之一 逃逸分析 Java与C/C++的编译器对比 即时编译器运行占用的是用户程序的运行时间,具有很大的时间压力。 Java语言虽然没有virtual关键字,但是使用虚方法的频率远大于C++,所以即时编译器进行优化时难度要远远大于C++的静态优化编译器。 Java语言是可以动态扩展的语言,运行时加载新的类可能改变程序类型的继承关系,使得全局的优化难以进行,因为编译器无法看见程序的全貌,编译器不得不时刻注意并随着类型的变化,而在运行时撤销或重新进行一些优化。 Java语言对象的内存分配是在堆上,只有方法的局部变量才能在栈上分配。C++的对象有多种内存分配方式。
Java 内存模型 用来屏蔽掉各种硬件和操作系统的内存访问差异 实现Java程序在各个平台下都能达到一致的并发效果 主内存与工作内存 所以的变量都存储在主内存,每条线程还有自己的工作内存,保存了被该线程使用到的变量的主内存副本拷贝。 线程对变量的所有操作(读取、赋值)都必须在工作内存中进行,不能直接读写主内存的变量。 不同的线程之间也无法直接访问对方工作内存的变量,线程间变量值的传递需要通过主内存。 Java内存模型定义了8种操作 lock unlock read load use assign store write 原子性 可见性 有序性 monitorenter 和 monitorexit 隐式使用 lock 和 unlock 操作 synchronized volatile final 本线程内观察,所有的操作都是有序的(线程内表现为串行的语义) 在一个线程中观察另一个线程,所有的操作都是无序的(指令重排序和工作内存与主内存同步延迟) volatile 保证变量对所有线程的可见性 禁止指令重排序优化 volatile变量读操作的性能消耗与普通变量几乎没有差别, 但是写操作则可能慢一些,因为需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行
实现线程的方式 使用内核线程实现 使用用户线程实现 使用用户线程+轻量级进程混合实现 线程调度 协同式线程调度:实现简单,没有线程同步的问题。但是线程执行时间不可控,容易系统崩溃。 抢占式线程调度:每个线程由系统来分配执行时间,不会有线程导致整个进程阻塞的问题。 线程安全 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 阻塞同步(互斥同步) 非阻塞同步 临界区、互斥量和信号量都是主要的互斥实现方式 synchronized java.util.concurrent包 ReentrantLock ReentrantLock比synchronized增加了高级功能 等待可中断、可实现公平锁、锁可以绑定多个条件。 锁优化 适应性自旋 锁消除 锁粗化 轻量级锁 偏向锁

上一篇     下一篇
spring web 注解

javassist 简介

Redis 性能监控指标

go压测工具 go-stress-testing

Goroutine与线程的区别

go 多模块例子