一、Java虚拟机基础介绍
首先看看以下例子:
public class Outer {
int x = 1;
public void doSomething() {
final int y = 2;
System.out.println(x);
System.out.println(y);
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.doSomething();
}
}
以上例子编译成 class 文件后,其是如何加载的?如何实现封装、继承、多态的?
1. JVM 简介
JVM 全称是 Java Virtual Machine(Java 虚拟机),也就是在计算机上再虚拟一个计算机。这和我们使用 VMWare 不一样——那个虚拟的东西你是可以看到的,而 JVM 是你看不到的,它存在于内存中。
计算机的基本构成是:运算器、控制器、存储器、输入和输出设备。JVM 也有这套元素:
运算器由硬件 CPU 处理;
但为了适应“一次编译,随处运行”的特性,JVM 引入了自己的指令集(类似汇编),并根据不同的 CPU 翻译成对应的机器语言。
2. 虚拟机的组成部分
主要包括两个子系统和两个组件:
- Class loader(类装载器)子系统
- Execution engine(执行引擎)子系统
- Runtime data area(运行时数据区域)组件
- Native interface(本地接口)组件

2.1 Class loader 子系统
根据全限定类名(如 java.lang.Object)加载 .class 文件内容到 Method Area(方法区)。
Java 程序员可以继承 java.lang.ClassLoader 编写自己的类加载器。
比如编写一个HelloWord.java程序,然后通过javac编译成class文件,那怎么才能加载到内存中被执行呢?Class Loader承担的就是这个责任,那不可能随便建立一个.class文件就能被加载的,Class Loader加载的class文件是有格式要求,在《JVM Specification》中式这样定义Class文件的结构:
ClassFile {
u4 magic;
u2 minor_version;
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];
}
例子对应的class文件如下

关键字段说明:
- access_flags:表示访问权限(如 public、final 等),其对应的值如下:
-

- this_class
-
该this_class的值必须是constant_pool表的一个有效的索引,且constant_pool表在该索引的项必须是一个CONSTANT_Class_info结构,其表示此class file定义的类或者接口。
- super_class
-
该super_class的值必须是0或者是constant_pool表的一个有效的索引,且constant_pool表在该索引的项必须是一个CONSTANT_Class_info结构,其表示此class file定义的类或者接口。 如果super_class的值是0,则改class文件必须是java.lang.Object类,它是唯一的没有超类的类。
- interfaces_count
-
该值给出该类或接口的直接超接口的个数。
- interfaces[]
-
表示该类或接口的直接超接口的结构CONSTANT_Class_info,其按照代码从左到右的顺序。
- fields_count
-
该值给出fileds表中的个数。
- fields[]
-
每项必须是一个给出该类或者接口类型中的一个域的完整描述的filed_info结构。该表只包括该类或者接口声明的域,不包括表示从超类或者超接口中继承的域。
-
field_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; } -
上述代码中access_flags的值如下:
-

- methods_count
-
该值给出methods表中的个数
- methods[]
-
每项必须是一个给出该类或者接口类型中的一个方法的完整描述的method_info结构。methods表不包括表示从超类或者超接口继承的方法的项。
-
method_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2 attributes_count; attribute_info attributes[attributes_count]; }上述代码中access_flags的值如下:
-


2.2 Execution engine 子系统
执行 class 文件中的字节码指令。
每个运行中的线程都有一个 Execution engine 实例。
Sun JDK 与 IBM JDK 的性能差异主要体现在 Execution engine 的实现优劣上。
2.3 Native interface 组件
用于与本地库(如 C/C++)交互,提供与其他语言通信的接口。
2.4 Runtime data area 组件(JVM 内存模型)
包含五个部分:
| Heap(堆) |
存放所有对象实例和数组 |
所有线程共享 |
| Method Area(方法区) |
存储类信息、静态变量、常量池等 |
所有线程共享 |
| Java Stack(Java 栈) |
以栈帧为单位存储方法调用状态(局部变量、操作数栈等) |
线程私有 |
| Program Counter(程序计数器) |
指向下一条要执行的字节码指令地址 |
线程 |

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



