1.首先要说明:什么是JVM?
JVM(Java Virtual Machine )是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。(百度获得)
个人的理解:JVM就是一个小型的操作系统。JVM与操作系统
麻雀虽小五脏俱全,JVM虽然不具备操作系统的某些组件,但是在内存管理与结构上还是非常相似的
2.JVM位置在哪?
我们都知道,计算机的操作系统(Windows,Mac,Linux)的层次在硬件之上,并与硬件体系交互地非常好,一台你新地计算机是没有操作系统的,需要安装,你可以安装任何系统,但只是我们大多数安装的都是Windows.这个JVM的位置就在操作系统之上,与操作系统有一些交互的关系。并且整个环境是由JRE(Java Runtime Enviroment)提供的。
3.java文件的执行过程
我们所写的java代码,无论是在记事本还是专用的写Java的软件(IDEA,eclipse等)写完了代码本身没有意义,只是在被编译器解析成.class字节码文件的时候被计算机读懂,然后放到类加载器(ClassLoader)中,被类加载器加载到JVM中,这个文件才有了’意义’。
4.JVM的体系结构
一个图清晰的表明了:
JVM的体系结构这个方法区还有一个非常别扭的名字:“非堆”
5.我们new 出来的对象在什么地方
Java是面向对象的语言,(他没有像C++那样残存了C的遗留,有结构体这种东西,我认为:结构体就是method和Field都是public的一种类),所以Java中的万物皆对象.
package JVMlearn
public class Car{
public static void main(String []args){
Car car1=new Car();
Car car2=new Car();
Car car3=new Car();
}
}
我们new出了三个Car类的对象,这些Car的名字:car1,car2…存放在Java的栈内,而这些名字的实例的字段放在了堆中,就比如car1,在栈中存放着他的名字car1和对应的堆内存地址0X1D81EB93,要引用到car1时,找到指向car1的堆内存地址,就找到car1了。
(获得内存地址方法:我们利用原生的toString方法就可以获得某一个对象的堆内存地址。)
我们打印出这三个对象的内存:
可见:这几个对象的内存地址不是连续的
总结:引用在Java栈中,实际对象的字段内容在堆中
6.类的加载器是如何加载类的?
这里不能不说的就是著名的双亲委派机制和沙箱安全机制.(关于沙箱安全的现在介绍的比较少了,本人只是了解)
话不多说,上源码:
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
PerfCounter.getParentDelegationTime().addTime(t1 - t0);
PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
我根据源码的思想,画出了这个UML图(99%原创)
这里需要说明:
1.JVM原生的加载器是我们获取不到的,因为其本身用C++语言编写
2.双亲委派机制的意义在于,安全的加载类,包括jdk-lib中的类和Coder自己编写的类。
3.这种安全性表现在当我们自己的类与lib中的类重名时ClassLoader会选择lib中的类加载Class而不会选择Coder字节写的类。
这只是我理解的JVM第一部分,今天由于时间关系没有写完,以后会有很多
部分的,我会将我自己学习心得和理解写在CSDN,希望大家多多批评指正!