JVM学习一:JVM之类加载器概况
18年转眼就3月份都快结束了,也就是说一个季度就结束了;而我也因为年前笔记本坏了,今天刚修好了,那么也应该继续学习和博客之旅了。今年的博客之旅,从JVM开始学起,下面我们就言归正传,进入正题。
一、Java虚拟机与程序的生命周期
一个运行时的Java虚拟机(JVM)负责运行一个Java程序。
当启动一个Java程序时,一个虚拟机实例诞生;当程序关闭退出,这个虚拟机实例也就随之消亡.
如果在同一台计算机上同时运行多个Java程序,将得到多个Java虚拟机实例,每个Java程序都运行于它自己的Java虚拟机实例中。
在如下几种情况下,Java虚拟机将结束生命周期:
1.执行了System.exit()方法
2.程序正常执行结束
3.程序在执行过程中遇到了异常或错误而异常终止
4.由于操作系统出现错误而导致Java虚拟机进程终止
二、类加载器ClassLoader
上面我们提到了java 程序是基于JVM之上运行的,那么我们知道我们编写的java程序,首先java编译器将我们的源代码编译成为字节码,然后由JVM将字节码load到内存中,接着我们的程序就可以创建对象了,我们知道JVM将字节码load到内存之后将将建立内存模型(JVM的内存模型我们将在稍后阐述),那JVM是怎么将类load到内存中的呢?对了,是通过Classloader;也就是我们说的类加载器。在讲解具体类加载执行流程前,我们来看一段代码:
class Singleton{ private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0; public Singleton() { counter1++; counter2++; } public static int getCounter1() { return counter1; } public static int getCounter2() { return counter2; } public static Singleton getInstance(){ return singleton; } } public class ClassLoaderTest { @SuppressWarnings("static-access") public static void main(String[] args) { Singleton singleton=Singleton.getInstance(); System.out.println("counter1:"+singleton.getCounter1()); System.out.println("counter2:"+singleton.getCounter2()); } }
我们先猜测一下运行结果,然后我们再来调换一下单实例生成的顺序,将:
private static Singleton singleton=new Singleton(); private static int counter1; private static int counter2 = 0;
修改为:
private static int counter1; private static int counter2 = 0; private static Singleton singleton=new Singleton();
然后我们会惊奇的发现,竟然结果是不一样的,这又是为什么呢? 学过JVM的的类加载器过程的估计一定知道了,但没有学过的,那么不要急,让我们一起来揭秘。
三、类的加载流程
紧接着上面的类型,让我们来看下类加载器到底是如何来加载的,流程如下:
即类加载经历了:加载 --> 连接 --> 初始化
1.加载:查找并加载类的二进制数据。
加载就是将二进制的字节码通过IO输入到JVM中,我们的字节码是存在于硬盘上面的,而所用的类都必须加载到内存中才能运行起来,加载就是通过IO把字节码从硬盘迁移到内存中。
详细分析见:《JVM学习二:JVM之类加载器之加载分析》:http://www.cnblogs.com/pony1223/p/8641015.html
2.连接:连接又分为三个步骤:
验证:确保被加载类的正确性。
即验证class文件是否符合JVM的要求。
准备:为类的静态变量分配内存,并将其初始化为默认值。
解析:把类中的符号引用转换为直接引用。
详细分析见:《JVM学习三:JVM之类加载器之连接分析》:http://www.cnblogs.com/pony1223/p/8641083.html
3.初始化:
为类的静态变量赋予正确的初始值,即在程序里为静态变量指定的初始值,或静态代码块中的赋值操作。
静态代码块是从上到下顺序执行的,可以对一个静态变量多次赋值,最后的结果为静态变量的初始值。
详细分析见:《JVM学习四:JVM之类加载器之初始化分析》:http://www.cnblogs.com/pony1223/p/8641181.html
参考资料:
圣思园张龙老师深入Java虚拟机系列