一、什么是 JVM

  JVM(Java Virtual Machine)是一个可以执行 Java 字节码文件(即 .class 文件)的虚拟机进程。当 Java 源文件能被成功编译成 .class 文件,就能在不同平台上的不同版本的 JVM 运行,因为 JVM 能将相同的 .class 文件解释称不同平台的机器码。正是因为 JVM 的存在,Java 被称为与平台无关的语言。

  一般而言,.java 文件经过编译后会得到 .class 文件,而将这个文件加载到内存之前需要先通过类加载器,先简单过一下图:

            

二、类加载过程

  类加载的过程为: 加载-->连接(验证-->准备-->解析)-->初始化。下面介绍其中的几个过程。

 1、加载

  这个过程主要是通过类的全限定名,例如 java.lang.String 这样带上包路径的类名,获取到字节码文件;然后将这个字节码文件代表的静态存储结构(可简单理解为对象创建的模板)存在方法区,并在堆中生成一个代表此类的 Class 类型的对象,作为访问方法区中“模板”的入口,往后创建对象的时候就按照这个模板创建。

  举个例子,有时候通过反射创建对象,像当初学 JDBC 时会通过 Class.getName("com.mysql.jdbc.Driver.class").newInstance() 创建对象,通过 Class 和相应的全限定类名获取到方法区中的“模板”然后创建对象。

        

 2、验证

  验证过程主要确保被加载的类的正确性。首先要先验证文件格式是否规范,如果只是通过 .class 后缀来辨别,那随便把后缀名改一下就可以跑程序了,那岂不是很容易出事。来看看字节码文件大概是长什么样的:

       

  注意看前缀 cafe babe(咖啡宝贝?)这只是验证的其中一个点,还会验证字节码文件里是否包含主次版本号等验证信息。

 3、准备

  这个阶段主要是给类变量(静态变量)分配方法区的内存并初始化。实例变量不是在这个阶段分配内存,实例变量是随着对象一起分配在堆中。另外,给静态变量初始化为零值或空值,比如public static int n=5;这里并不是马上给 n 这个变量赋值为 5,而是先将其赋值为 0,类似的,如果是引用数据类型,则默认为 null。还有一点需要注意的是,对于 final 类型的数据,必须在程序内给它赋值,系统不会自动初始化,例如 static String str = "hello" + “world”;String 是 final 类型的,在编译阶段就给它优化成 static String str = "helloworld” ,并且将 "helloworld" 放进了常量池。

 4、初始化

  这个阶段就是将静态变量赋值为初始值,还是 public static int n=5; 这回给 n 赋值为 5 了。

三、类加载器

        

  启动类加载器是由C/C++写的,主要负责加载 jre\lib 目录下的类;扩展类加载器主要负责加载 jre\lib\ext 目录下的类;而应用程序类加载器主要负责加载我们自己编写的类;当然还能自己写类加载器,即自定义加载器。程序主要由前面三个类加载器相互配合加载的。

public class Main {
public static void main(String[] args) {
Main main = new Main();
System.out.println(main.getClass().getClassLoader());
System.out.println(main.getClass().getClassLoader().getParent());
System.out.println(main.getClass().getClassLoader().getParent().getParent());
}
}  

  由于启动类加载器是 C/C++ 语言写的,所以输出为 null

 双亲委派机制

  在类加载的过程中,存在着双亲委派机制,即当要加载一个类时,先由父类加载器加载,当父类加载器没办法加载时,才由下面的加载器加载,来看一个程序:

package java.lang;   // 自定义的包

public class String {
public static void main(String[] args) {
System.out.println("这是自定义的java.lang.String类");
}
}

  

  由于 jre\lib\ext 中存在 java.lang.String 类,当加载该类的时候,根据全限定名进行查找,找到后由启动类加载器加载,发现 String 类中不包含 main() 方法,因此程序出错。

JVM 之类加载器的更多相关文章

  1. JVM自定义类加载器加载指定classPath下的所有class及jar

    一.JVM中的类加载器类型 从Java虚拟机的角度讲,只有两种不同的类加载器:启动类加载器和其他类加载器. 1.启动类加载器(Boostrap ClassLoader):这个是由c++实现的,主要负责 ...

  2. 【深入理解JVM】类加载器与双亲委派模型 (转)

    出处: [深入理解JVM]类加载器与双亲委派模型 加载类的开放性 类加载器(ClassLoader)是Java语言的一项创新,也是Java流行的一个重要原因.在类加载的第一阶段“加载”过程中,需要通过 ...

  3. 1.1 jvm核心类加载器--jdk源码剖析

    目录 前提: 运行环境 1. 类加载的过程 1.1 类加载器初始化的过程 1.2 类加载的过程 1.3 类的懒加载 2. jvm核心类加载器 3. 双亲委派机制 4. 自定义类加载器 5. tomca ...

  4. 【JVM】JVM之类加载器

    一.前言 首先,小小测试,看是否已经掌握了JVM类加载的过程 1.1.测试一 class Singleton { private static Singleton sin = new Singleto ...

  5. JVM之类加载器下篇

    除了自定义的类加载之外,jvm存在三种类加载器,并以一种父委托的加载机制进行加载. --启动类加载器,又称根加载器,是一个native的方法,使用c++实现.在java中我们用null标识,用于加载j ...

  6. 【深入理解JVM】类加载器与双亲委派模型

    原文链接:http://blog.csdn.net/u011080472/article/details/51332866,http://www.cnblogs.com/lanxuezaipiao/p ...

  7. JVM学习一:JVM之类加载器概况

    18年转眼就3月份都快结束了,也就是说一个季度就结束了:而我也因为年前笔记本坏了,今天刚修好了,那么也应该继续学习和博客之旅了.今年的博客之旅,从JVM开始学起,下面我们就言归正传,进入正题. 一.J ...

  8. (转)JVM——自定义类加载器

    背景:为什么要自定义,如何自定义,实现过程 转载:http://blog.csdn.net/SEU_Calvin/article/details/52315125 0. 为什么需要自定义类加载器 网上 ...

  9. JVM虚拟机-类加载器子系统

    转自博客:http://www.cnblogs.com/muffe/p/3541189.html   还有一些自己补充的知识点 一.类加载器基本概念 顾名思义,类加载器(class loader)用来 ...

  10. 深入理解JVM一类加载器原理

    我们知道我们编写的java代码,会经过编译器编译成字节码文件(class文件),再把字节码文件装载到JVM中,映射到各个内存区域中,我们的程序就可以在内存中运行了.那么字节码文件是怎样装载到JVM中的 ...

随机推荐

  1. Hadoop监控指标项

    配置 修改$HADOOP_HOME/etc/hadoop/hadoop-env.sh # 在配置namenode和datanode时都会有用到JMX_OPTS的代码,是为了减少重复提取出的公共代码 e ...

  2. sqlmap自动注入 --REQUEST

    --delay=“参数” 每次http(s)请求之间的延迟时间,浮点数,单位为秒,默认无延迟 --timeout=“参数” 请求超时,浮点数,默认为30秒 --retries=“参数” http(s) ...

  3. vue router 如何使用params query传参,以及有什么区别

    写在前面: 传参是前端经常需要用的一个操作,很多场景都会需要用到上个页面的参数,本文将会详细介绍vue router 是如何进行传参的,以及一些小细节问题.有需要的朋友可以做一下参考,喜欢的可以点波赞 ...

  4. 堆里面的分区:Eden,Survivor(from+ to),老年代,各自的特点

    堆里面分为新生代和老生代(java8取消了永久代,采用了Metaspace),新生代包含Eden+Survivor区,survivor区里面分为from和to区,内存回收时,如果用的是复制算法,从fr ...

  5. ANR错误分析

    链接1:https://www.cnblogs.com/xiyuan2016/p/6740623.html 链接2:https://www.jianshu.com/p/3959a601cea6

  6. UVA 816 -- Abbott's Revenge(BFS求最短路)

     UVA 816 -- Abbott's Revenge(BFS求最短路) 有一个 9 * 9 的交叉点的迷宫. 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可).进入一个交叉 ...

  7. leetcode 140 单词拆分2 word break II

    单词拆分2,递归+dp, 需要使用递归,同时使用记忆化搜索保存下来结果,c++代码如下 class Solution { public: //定义一个子串和子串拆分(如果有的话)的映射 unorder ...

  8. Java反序列化漏洞从入门到深入(转载)

    前言 学习本系列文章需要的Java基础: 了解Java基础语法及结构(菜鸟教程) 了解Java面向对象编程思想(快速理解请上知乎读故事,深入钻研建议买本<疯狂Java讲义>另外有一个刘意老 ...

  9. 【python3】configparser读取ini配置文件

    在应用过程中,发现下面这个问题: cf=configparser.ConfigParser()读取配置文件时,如果数据包含%这们析特殊符号,就会报出上面的错误,使用cf = configparser. ...

  10. 阶段3 3.SpringMVC·_01.SpringMVC概述及入门案例_04.入门程序之搭建开发环境

    选择骨架构建 默认选中next-然后finish后就会去网上下载插件.会比较耗费时间. 添加一组键值对: archetypeCatalog internal 添加了这组坚持对,就可以解决Mavn项目创 ...