聊聊JVM

聊聊JVM

1.为什么java需要虚拟机?

JVM,Java Virtual Machine,中文名就是虚拟机。Java 的原始码文件格式名为*.java,经过编译器翻译过后,会变成*.class的格式文件位元码。如果想要执行这个位元码档案,目标平台上必须安装有JVM(Java Virtual Machine)。JVM会将位元码翻译为相应平台支持的语言。

2.市面上有哪些jvm?

目前市面上就只有三种主流的JVM:SUN、BEA和IBM。

3.jvm运行时数据区,每个数据区都存储啥内容?

JVM运行时的数据区结构

参考:jvm运行时数据区

4.jvm相关命令?

jps:JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。

jstat: JVM statistics Monitoring是用于监视虚拟机运行时状态信息的命令,它可以显示出虚拟机进程中的类装载、内存、垃圾收集、JIT编译等运行数据。

jmap: JVM Memory Map不仅能生成dump文件,还阔以查询finalize执行队列、Java堆和永久代的详细信息,如当前使用率、当前使用的是哪种收集器等。

jhat:JVM Heap Analysis Tool命令是与jmap搭配使用,用来分析jmap生成的dump,jhat内置了一个微型的HTTP/HTML服务器,生成dump的分析结果后,可以在浏览器中查看。在此要注意,一般不会直接在服务器上进行分析,因为jhat是一个耗时并且耗费硬件资源的过程,一般把服务器生成的dump文件复制到本地或其他机器上进行分析。

jstack:jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

jinfo:JVM Configuration info这个命令作用是实时查看和调整虚拟机运行参数。
之前的jps -v口令只能查看到显示指定的参数,如果想要查看未被显示指定的参数的值就要使用jinfo口令

参考:jvm命令

5.java class文件格式?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ClassFile { 
u4 magic; // 魔法数字,表明当前文件是.class文件,固定0xCAFEBABE
u2 minor_version; // 分别为Class文件的副版本和主版本
u2 major_version;
u2 constant_pool_count; // 常量池计数
cp_info constant_pool[constant_pool_count-1]; // 常量池内容
u2 access_flags; // 类访问标识
u2 this_class; // 当前类
u2 super_class; // 父类
u2 interfaces_count; // 实现的接口数
u2 interfaces[interfaces_count]; // 实现接口信息
u2 fields_count; // 字段数量
field_info fields[fields_count]; // 包含的字段信息
u2 methods_count; // 方法数量
method_info methods[methods_count]; // 包含的方法信息
u2 attributes_count; // 属性数量
attribute_info attributes[attributes_count]; // 各种属性
}
6.java对象创建的过程?

对象创建过程

7.对象的内存分布?

1:对象内存分配在堆中(绝大部分普通Java对象,像Class对象是分配在方法区中的)
2:对象开始的部分是对象头,包括两部分信息
第一部分是自身运行时数据,存放了跟对象有关的信息,如哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等
第二部分是类型指针,即对象指向它的类元数据的指针。可以通过它知道该对象是哪个类的实例
3:中间是实例数据,就是在程序代码中定义的各种类型的字段内容。包括从父类继承下来的。执行的时候也要执行父类的初始化

4:最后是对齐填充,没有特殊含义,就是为了让对象大小为8的整数倍

8.对象的访问定位?

Java程序需要通过栈上的reference数据来操作堆上的具体对象。reference数据只是一个指向对象的引用,具体的对象访问根据不同虚拟机有不同的实现,主流的访问方式有两种:使用句柄直接指针

使用句柄:

如果通过句柄来访问对象,Java堆中会划出一块内存作为句柄池,reference中存储句柄地址,而句柄中包含对象的实例数据与类型数据各自的地址。这样就能访问到对象了。

通过句柄访问对象

直接指针:

直接指针,就是指reference中直接存储对象的地址。但是Java堆对象的布局中就必须考虑如何防止访问类型数据相关信息。

通过直接指针访问对象

这两种对象访问方式,各有优势,但是HotSpot使用的是指针对象访问,但是句柄访问对象在整个软件开发范围中也是十分常见的。

9.讲讲常量池,String.intern()方法理解?

参考:String.intern()方法理解