JVM启动过程包括:加载、连接、初始化
1.加载:就是将class文件加载到内存。详细的说是,将class文件加载到运行时数据区的方法区内(JDK7是方法区,JDK8对应的是Metaspace),然后创建一个java.lang.Class对象,用来封装类在方法区类的数据结构。JVM规范并未说明Class对象位于何处,Hotspot虚拟机将其放在了方法区
有两种类型的类加载器:
1.1JVM自带提供的三类加载器:根类加载器Bootstrap Classloader(C++写的, 程序员无法在JAVA代码中获得该类)
扩展加载器Extension Classloader,使用Java代码实现
系统加载器System ClassLoader,也叫应用加载器 Application Classloader,使用Java代码实现
1.2用户自定义的类加载器,都是java.lang.ClassLoader的子类
2.连接分为三步 2.1.验证:检查被加载的类的正确性;
2.2.初始化(或者叫准备更好):接着将静态变量初始化为默认值,比如一个类中有一句private static int num=1; 实际上在这一步的时候,只是将num初始化为默认值0
2.3.解析:把类中的符号引用转换为直接引用,这个其实也好理解,毕竟所有类都加载好,才能真正进行直接引用,但是类的加载也有现后顺序之分,所以如果先加载的类引用了后加载的类,只有等到后者完成加载,才能真正引用到内存中的地址
3. 初始化。"任何JVM实现,必须在每个类或接口被JAVA程序"首次主动使用时"才初始化它们",这一步将静态变量最终赋值,比如上面举例钟,num变量将被赋值为1。静态代码块也在这一步被执行
例子:下面这个程序,的执行过程:
package com.test.jvm.common; class Singleton {
private static Singleton singleton = new Singleton();
public static int num1;
public static int num2=0; public Singleton() {
num1++;
num2++;
}
public static Singleton getSingleton() {
return singleton;
}
} public class Main {
public static void main(String[] args) {
Singleton singleton = Singleton.getSingleton();
System.out.println(Singleton.num1);
System.out.println(Singleton.num2);
}
}
首先加载class类,因为class类主动使用了Singleton类的方法,于是Singleton类也开始加载,加载完毕后Singleton类的static变量开始赋予默认值,注意是默认值而不是初始值,于是singleton被赋值null,
num1和num2均赋值为0,然后开始初始化,从上到下的执行顺序,singleton被初始化为new Singleton(),这导致构造函数的调用,于是num1和num2都被赋值为1,singleton初始化完成之后,num1接着初始化,可是num1没有初始值,于是num1保持为1不变,然后轮到num2初始化,num2被初始化为0。后面就略了,所以最后执行结果是1和0
附类的初始化时机:
======================================================================================================================================================
package com.test.jvm.common; /**
* 学习类的加载过程 当静态变量为final的时候
*/
class FinalTest {
public static final int x = 6/3;
static {
System.out.println("FinalTset static block");
}
} public class Main {
public static void main(String[] args) {
System.out.println(FinalTest.x);
}
}
执行结果为2,并没有输出那句话,这是因为FinalTest1并没有得到初始化,没有得到初始化的原因是6/3是编译时常量
package com.test.jvm.common; import java.util.Random; /**
* 学习类的加载过程 当静态变量为final的时候
*/
class TestClass2 {
public static final int x = new Random().nextInt(100);//0~99
static {
System.out.println("FinalTset2 static block");
}
} public class FianlTest2 {
public static void main(String[] args) {
System.out.println(TestClass2.x);
}
}
结果:
FinalTset2 static block
84
这是因为FinalTest2得到了初始化,原因是 new Random().nextInt(100); 是运行时才能确定的量
=====================================================================================
package com.test.jvm.common; class Parent3 {
static int a = 3;
static {
System.out.println("Parent3 static block");
}
} class Child3 extends Parent3 {
static {
System.out.println("Child3 static block");
}
} /**
* 只有当程序访问的静态变量或静态方法确实在当前类或者当前接口中定义时,才可以认为是对类或接口的主动使用
*/
public class StaticTest3 {
public static void main(String[] args) {
System.out.println(Child3.a);
}
}
运行结果:
Parent3 static block
3
====================================================================================
package com.test.jvm.common; class CL {
static {
System.out.println("Class CL");
}
} /**
* 调用ClassLoader类的loadClass方法加载一个类,并不是对类的主动使用,不会导致类的初始化
*/
public class StaticTest4 {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> clazz = loader.loadClass("com.test.jvm.common.CL");
System.out.println("-----------------------");
clazz = Class.forName("com.test.jvm.common.CL");
}
}
运行结果:
-----------------------
Class CL
JVM启动过程的更多相关文章
-
JVM系列(一):jvm启动过程速览
jvm是java的核心运行平台,自然是个非常复杂的系统.当然了,说jvm是个平台,实际上也是个泛称.准确的说,它是一个java虚拟机的统称,它并不指具体的某个虚拟机.所以,谈到java虚拟机时,往往我 ...
-
038.[转] JVM启动过程与类加载
From: https://blog.csdn.net/luanlouis/article/details/40043991 Step 1.根据JVM内存配置要求,为JVM申请特定大小的内存空间 ? ...
-
JVM启动过程——JVM之一
JVM是Java程序运行的环境,同时是一个操作系统的一个应用程序进程,因此它有自己的生命周期,也有自己的代码和数据空间. JVM体系主要是两个JVM的内部体系结构分为三个子系统和两大组件,分别是:类装 ...
-
JVM启动过程 类加载器
下图来自:http://blog.csdn.net/jiangwei0910410003/article/details/17733153 package com.test.jvm.common; i ...
-
JVM 启动参数及原理 转
Java虚拟机(JVM)是Java应用的运行环境,从一般意义上来讲,JVM是通过规范来定义的一个虚拟的计算机,被设计用来解释执行从Java源码编译而来的字节码.更通俗地说,JVM是指对这个规范的具体实 ...
-
CentOS7 Tomcat 启动过程很慢,JVM上的随机数与熵池策略
1. CentOS7 Tomcat 启动过程很慢 在centos启动官方的tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的: <co ...
-
Openfire的启动过程与session管理
说明 本文源码基于Openfire4.0.2. Openfire的启动 Openfire的启动过程非常的简单,通过一个入口初始化lib目录下的openfire.jar包,并启动一个 ...
-
hive配置以及在启动过程中出现的问题
一.hive配置 1.安装环境 在hadoop-1.2.1集群上安装hive-1.2.1 2.将hive-1.2.1环境变量添加到PATH路径下 使用如下命令打开配置文件 nano /etc/prof ...
-
JVM类加载过程学习总结
JVM类加载过程学习总结 先不说JVM类加载的原理,先看实例: NormalTest类,包含了一个静态代码块,执行的任务就是打印一句话. /** * 在正常类加载条件下,看静态代码块是否会执行 * @ ...
随机推荐
-
Spring注解学习
参考链接 http://blog.csdn.net/xyh820/article/details/7303330/
-
黄聪:如何用Jquery或者插件解除网页禁用右键复制的限制(转)
1.随便打开一个网址,放到收藏夹中. 2.复制下面的代码,替换原来网址的URL 选中复制以下代码 javascript:(function(){var doc=document;var bd=doc. ...
-
java中如何获取系统时间
需要引入的包有: import java.util.Date; 此为获取当前系统时间,合适为“1991-01-01” String now = ""; SimpleDateF ...
-
IO流输入 输出流 字符字节流
一.流 1.流的概念 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作. ...
-
从0开始的Python学习002python的数据类型
在创建变量的时候不用声明数据类型 # 创建变量 a = 10 # 打印变量值 print(a) 结果如下: 这种感觉和Java有很大的不同,感觉python很神奇,数据的类型是python自己决定的. ...
-
Oracle下SQL学习笔记
主机字符串:as sysdba alter user scott account unlock;//解锁scott,不会就谷歌检索 DML语句,增.删.查.改 select语句:熟悉表结构 desc ...
-
C++二级指针第一种内存模型(指针数组)
二级指针第一种内存模型(指针数组) 指针的输入特性:在主调函数里面分配内存,在被调用函数里面使用指针的输出特性:在被调用函数里面分配内存,主要是把运算结果甩出来 指针数组 在C语言和C++语言中,数组 ...
-
微信小程序里使用过滤器
新建一个 filter.wxs文件 function formatString(val, len) { if (val.length > len) { return val.substring( ...
-
使用VMWare虚拟机创建CentOS版本号的Linux学习环境(每一步都有截图与说明)
学习Android开发.假设不学习Linux的基本使用,总感觉心里过意不去,由于毕竟Android还是搭载在Linux的基础之上的. 因此.学习一种Linux系统的基本操作.对我们以后的学习还是非常有 ...
-
asp.net mvc 请求处理流程,记录一下。
asp.net mvc 请求处理流程,记录一下.