JVM是什么?
JVM(Java Virtual Machine,Java虚拟机):java程序首先需要通过javac来编译,生成.class文件,然后通过java.exe(windows上)去运行,实际上java.exe是会去装载jvm.dll不同平台下是不一样的(linux下的libjvm.dll)。
jvm是jre的一部分,他是一个虚构出来的计算机,拥有自己完善的硬件架构,如处理器、堆栈、寄存器等。
更多关于JVM的概念介绍:百度百科
JVM结构
JVM内部大概分为三个部分,分别是类装载器(ClassLoader)子系统,运行时数据区(Runtime Data Area)、和执行引擎(ExecutionEngine):
类装载器(ClassLoader)子系统
其主要作用是将class文件进行装载,然后可以得到该类的类类型,然后类类型的实例化就是新建每个新的对象,但是他们的信息都是与模板一样:如下图
类加载器出去用户自定义有三种:
- BootStrap:启动类加载器,C++编写的,java的根基 rt.jar (Runtime)
- Extension:扩展类加载器 Java 用于java扩展的 jar
- AppClassLoader:应用程序类加载器,也叫系统类加载器,加载当前应用的classpath的所有类
参考代码,查看结果:
public class MyObjectDemo01 {
public static void main(String[] args) {
Object object = new Object();
// System.out.println(object.getClass().getClassLoader().getParent().getParent());
// System.out.println(object.getClass().getClassLoader().getParent());
// 这是属于java自己的类,是使用BootStrap加载器进行加载的,所以上面两个写出时会报空指针异常找不到其父类 null
System.out.println(object.getClass().getClassLoader());
MyObjectDemo01 myObjectDemo01 = new MyObjectDemo01();
// null
System.out.println(myObjectDemo01.getClass().getClassLoader().getParent().getParent());
// sun.misc.Launcher$ExtClassLoader@3a71f4dd
System.out.println(myObjectDemo01.getClass().getClassLoader().getParent());
// sun.misc.Launcher$AppClassLoader@18b4aac2 自己定义的类,走的是AppClassLoader加载器
// sun.misc.Launcher JVM的入口程序
System.out.println(myObjectDemo01.getClass().getClassLoader());
}
}
null
null
sun.misc.Launcher$ExtClassLoader@3a71f4dd
sun.misc.Launcher$AppClassLoader@18b4aac2
首先是自己的类,会通过AppClassLoader进行类加载,但不是第一次就是通过该加载器加载,后面会讲为什么。而BootStrap是使用c写的,所以打印的时候会是null。
双亲委派
首先参考一段代码:
public class String {
public static void main(String[] args) {
/**
* 错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
* public static void main(String[] args)
* 否则 JavaFX 应用程序类必须扩展javafx.application.Application
*/
System.out.println("我是自己定义的类...");
}
}
我这里的包名:package java.lang;这样情况如果java不存在一个类似于安全校验的东西,那么下一个使用String类的对象就不知道改使用哪个,所以引出双亲委派和沙箱安全
当一个类接收到了类加载器请求,该发出请求的类加载器不会自己先去尝试加载这个类,而是将这个请求委派给父类去完成,所以,所有的加载请求都会传送到启动类加载器(BootStrap)进行加载,如果父类反馈自己无法完成此次加载(就是在其加载路径下没有找到对应的class文件),子类加载器才会去尝试自己加载。
这样做的好处就是,不管是使用什么类加载器去加载String,都会先通过父加载器(Bootstrap)进行加载,这样能保证最后加载到的String对象是同一个对象.
沙箱安全:JVM将不同的代码放在不同的域中,从而控制权限
谢谢大家阅读!!