JVM(Java虚拟机)充当运行Java应用程序的运行时引擎。JVM是实际上调用Java代码中存在的main方法的一种。JVM是JRE(Java运行时环境)的一部分。
Java应用程序称为WORA(可在任何地方写入一次)。这意味着程序员可以在一个系统上开发Java代码,并且可以期望它在任何其他启用Java的系统上运行,而无需进行任何调整。由于JVM,所有这些都是可能的。
当我们编译.java文件时,Java编译器会生成具有与.java文件中相同的类名的.class文件(包含字节码)。当我们运行它时,此.class文件进入各个步骤。这些步骤共同描述了整个JVM:
类加载器子系统
它主要负责三个活动。
- 载入
- 链接
- 初始化
加载:类加载器读取.class文件,生成相应的二进制数据并将其保存在方法区域中。对于每个.class文件,JVM将以下信息存储在方法区域中。
- 加载的类及其直接父类的全限定名称。
- .class文件与类或接口或枚举
- 修饰符,变量和方法信息等
加载.class文件后,JVM创建类型为Class的对象来表示该文件在堆内存中。请注意,该对象的类型为java.lang包中预定义的Class 。程序员可以使用此Class对象来获取类级别的信息,例如类名称,父名称,方法和变量信息等。要获取此对象引用,我们可以使用Object类的getClass()方法。
// A Jav代码,展示被JVM创建的类实例中,代表.class且被储蓄在内存中的信息
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// 创建测试类
public class Test
{
public static void main(String[] args)
{
Student s1 = new Student();
// 得到claas信息
Class c1 = s1.getClass();
// 打印c1类型
System.out.println(c1.getName());
// 在一个array中得到所有防范
Method m[] = c1.getDeclaredMethods();
for (Method method : m)
System.out.println(method.getName());
// 在一个array中,得到所有fields
Field f[] = c1.getDeclaredFields();
for (Field field : f)
System.out.println(field.getName());
}
}
// 测试代码
class Student
{
private String name;
private int roll_No;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getRoll_no() { return roll_No; }
public void setRoll_no(int roll_no) {
this.roll_No = roll_no;
}
}
输出:
Student
getName
setName
getRoll_no
setRoll_no
name
roll_No
注意:对于每个加载的.class文件,仅创建一个 Class对象。
Student s2 = new Student();
// c2和c1指向同一个实例对象
Class c2 = s2.getClass();
System.out.println(c1==c2); // true
链接:执行验证,准备和(可选)解决方案。
- 验证:它确保.class文件的正确性,即检查该文件的格式是否正确,是否由有效的编译器生成。如果验证失败,我们将获得运行时异常java.lang.VerifyError。
- 准备:JVM为类变量分配内存,并将内存初始化为默认值。
- 解决方案:这是将类型中的符号引用替换为直接引用的过程。通过搜索方法区域以找到引用的实体来完成此操作。
初始化:在此阶段,所有静态变量都分配有在代码和静态块(如果有)中定义的值。在类中从上到下执行,在类层次结构中从上到下执行。
通常,有三种装载机:
- 引导程序类加载器:每个JVM实现都必须具有一个引导程序类加载器,能够加载受信任的类。它加载JAVA_HOME / jre / lib目录中存在的核心Java API类。该路径通常称为引导路径。它以C,C++等本地语言实现。
- 扩展类加载器:它是引导类加载器的子级。它将加载扩展目录JAVA_HOME/jre/lib/ext(扩展路径)或Java.ext.dirs系统属性指定的任何其他目录中存在的类。它由sun.misc.Launcher $ ExtClassLoader类在Java中实现。
- 系统/应用程序类加载器:它是扩展类加载器的子级。它负责从应用程序类路径加载类。它在内部使用映射到java.class.path的环境变量。它也由sun.misc.Launcher $ AppClassLoader类在Java中实现。
// Java代码,展示类载入的子系统 public class Test { public static void main(String[] args) { // string类被bootstrap载入器载入,bootstrap loader不是java的一个对象,所有是null System.out.println(String.class.getClassLoader()); // 测试类,被Application载入器载入 System.out.println(Test.class.getClassLoader()); } }
输出:
null sun.misc.Launcher$AppClassLoader@73d16e93
0