1、JAVA弱引用
弱引用需要用 WeakReference 类来实现,它比软引用的生存期更短,对于只有弱引用的对象来说,只要垃圾回收机制一运行,不管 JVM 的内存空间是否足够,总会回收该对象占用的内存。
2、什么是堆
存放对象实例,所有的对象和数组都要在堆上分配。 是 JVM 所管理的内存中最大的一块区域。
3、什么是程序计数器
当前线程所执行的行号指示器。是 JVM 内存区域最小的一块区域。执行字节码工作时就是利用程序计数器来选取下一条需要执行的字节码指令。
4、各种回收器,各自优缺点,重点CMS、G1
图来源于《深入理解Java虚拟机:JVM高级特效与最佳实现》,图中两个收集器之间有连线,说明它们可以配合使用.
1、 Serial收集器,串行收集器是最古老,最稳定以及效率高的收集器,但可能会产生较长的停顿,只使用一个线程去回收。
2、 ParNew收集器,ParNew收集器其实就是Serial收集器的多线程版本。
3、 Parallel收集器,Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量。
4、 Parallel Old收集器,Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程“标记-整理”算法
5、 CMS收集器,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它需要消耗额外的CPU和内存资源,在CPU和内存资源紧张,CPU较少时,会加重系统负担。CMS无法处理浮动垃圾。CMS的“标记-清除”算法,会导致大量空间碎片的产生。
6、 G1收集器,G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器、以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。
5、可以描述一下 class 文件的结构吗?
1、 Class 文件包含了 Java 虚拟机的指令集、符号表、辅助信息的字节码(Byte Code),是实现跨操作系统和语言无关性的基石之一。
2、 一个 Class 文件定义了一个类或接口的信息,是以 8 个字节为单位,没有分隔符,按顺序紧凑排在一起的二进制流。
3、 用 "无符号数" 和 "表" 组成的伪结构来存储数据。
4、 无符号数:基本数据类型,用来描述数字、索引引用、数量值、字符串值,如u1、u2 分别表示 1 个字节、2 个字节
10、 表:无符号数和其他表组成,命名一般以 "_info" 结尾
组成部分
1、 魔数 Magic Number
Class 文件头 4 个字节,0xCAFEBABE
作用是确定该文件是 Class 文件
2、 版本号
4 个字节,前 2 个是次版本号 Minor Version,后 2 个主版本号 Major Version
从 45 (JDK1.0) 开始,如 0x00000032 转十进制就是 50,代表 JDK 6
低版本的虚拟机跑不了高版本的 Class 文件
3、 常量池
常量容量计数值(constant_pool_count),u2,从 1 开始。如 0x0016 十进制 22 代表有
21 项常量
每项常量都是一个表,目前 17 种
特点:Class 文件中最大数据项目之一、第一个出现表数据结构
4、 访问标志
2 个字节,表示类或接口的访问标志
5、 类索引、父类索引、接口索引集合
类索引(this_class)、父类索引(super_class),u2
接口索引集合(interfaces),u2 集合
类索引确定类的全限定名、父类索引确定父类的全限定名、接口索引集合确定实现接口
索引值在常量池中查找对应的常量
6、 字段表(field_info)集合
描述接口或类申明的变量
fields_count,u2,表示字段表数量;后面接着相应数量的字段表
9 种字段访问标志
7、 方法表(method_info)集合
描述接口或类申明的方法
methods_count,u2,表示方法表数量;后面接着相应数量的方法表
12 种方法访问标志
方法表结构与字段表结构一致
8、 属性表(attribute_info)集合
class 文件、字段表、方法表可携带属性集合,描述特有信息
预定义 29 项属性,可自定义写入不重名属性
6、类的实例化顺序
比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序
先静态、先父后子。
先静态:父静态 > 子静态
优先级:父类 > 子类 静态代码块 > 非静态代码块 > 构造函数
一个类的实例化过程:
1、 父类中的static代码块,当前类的static
2、 顺序执行父类的普通代码块
3、 父类的构造函数
4、 子类普通代码块
5、 子类(当前类)的构造函数,按顺序执行。
6、 子类方法的执行,
7、怎么打出线程栈信息?
输入jps,获得进程号。top -Hp pid 获取本进程中所有线程的CPU耗时性能 jstack pid命令查看当前java进程的堆栈状态 或者 jstack -l > /tmp/output.txt 把堆栈信息打到一个txt文件。可以使用fastthread 堆栈定位(fastthread.io)
8、程序计数器是什么?
程序计数器是一块较小的内存空间,可以看作当前线程所执行字节码的行号指示器。字节码解释器工作时通过改变计数器的值选取下一条执行指令。分支、循环、跳转、线程恢复等功能都需要依赖计数器完成。是唯一在虚拟机规范中没有规定内存溢出情况的区域。
如果线程正在执行 Java 方法,计数器记录正在执行的虚拟机字节码指令地址。如果是本地方法,计数器值为 Undefined。
9、JVM的引用类型有哪些?
引用内型:
强引用:
当内存不足的时候,JVM宁可出现OutOfMemoryError错误停止,也需要进行保存,并且不会将此空间回收。在引用期间和栈有联系就无法被回收
软引用:
当内存不足的时候,进行对象的回收处理,往往用于高速缓存中;mybatis就是其中
弱引用:
不管内存是否紧张,只要有垃圾了就立即回收
幽灵引用:
和没有引用是一样的
10、Serial 与 Parallel GC 之间的不同之处?
Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而parallel 收集器使用多个 GC 线程来执行。