【JVM】JVM之类加载器

简介: 首先,小小测试,看是否已经掌握了JVM类加载的过程

首先,小小测试,看是否已经掌握了JVM类加载的过程


1.1、测试一


class Singleton {
    private static Singleton sin = new Singleton();
    public static int counter1;
    public static int counter2 = 0;
    private Singleton() {
        counter1++;
        counter2++;
    }
    public static Singleton getInstance() {
        return sin;
    }
}
public class Test {
    public static void main(String[] args) {
        Singleton sin = Singleton.getInstance();
        System.out.println(sin.counter1);
        System.out.println(sin.counter2);
    }
}  

输出结果为:


  1 3 ?

  1 0 ?  

  0 1?

  1.2、测试二:


class Singleton {  
    public static int counter1;
    public static int counter2 = 2;
    private static Singleton sin = new Singleton();
    private Singleton() {
        counter1++;
        counter2++;
    }
    public static Singleton getInstance() {
        return sin;
    }
}
public class Test {
    public static void main(String[] args) {
        Singleton sin = Singleton.getInstance();
        System.out.println(sin.counter1);
        System.out.println(sin.counter2);
    }
}  


输出结果为:


  1 3 ?

  1 2 ?  

  0 1?


正确的输出结果如下:


测试一的结果为:1 0

测试二的结果为:1 3


如果对结果有疑惑或者不知道原因的园友需要了解类加载器的具体细节,相信看了本篇文章,一定会解开您的疑惑。废话不多说,直奔主题。


二、背景知识


  2.1、Java虚拟机通过装(加)载、连接、初始化一个Java类型,使该类型可以被正在运行的Java程序所使用。 

 

  ①装(加)载类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区中,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构,之后可以用Class对象进行相关的反射操作。


  ②连接分为三个子步骤  

  

    验证:确保被加载的类的正确性


    准备:为类的静态变量分配内存,并将其初始化为默认值


    解析: 把类中的符号引用转换为直接引用


  ③初始化为为类的静态变量赋予正确的初始值


  如下为流程图:


image.png


2.2、关于初始化的细节 

 

  所有的Java虚拟机实现必须在每个类或接口被Java程序“首次主动使用”时才初始化他们,下面六种情况符合首次主动使用要求。

    

    ① 创建类的实例  

  

    ②访问某个类或接口的非常量静态域,或者对该非常量静态域赋值


    ③ 调用类的静态方法


    ④反射(如Class.forName(“com.test.Test”)(其中Test为一个类),而Test.class就不是首次使用)


    ⑤初始化一个类的子类


    ⑥Java虚拟机启动时被标明为启动类的类(Test)(Test为包含了程序入口main方法的类)


  2.3、如论如何,如果一个类型在其首次主动使用之前还没有被装(加)载和连接的话,那它必须在此时进行加载和连接,这样它才能够被初始化。


三、问题分析


  3.1、读到这里应该可以分析出为什么之前的程序会输出那样的结果,下面我们来一起分析一下整个过程。


  ①对于测试一的结果分析


  首先在main中调用了Singleton的getInstance类静态方法,符合第③条,需要初始化类,即初始化Singleton,首先需要装(加)载和连接,从硬盘中加载进内存,然后进入连接的验证,没有问题,OK,进入准备阶段,此时,将类变量sin、counter1、counter2分配内存,并初始化默认值null、0、0。紧接着,将符号引用转化为直接引用(暂  时不不要太了解,程序中就是将Singleton符号转化为在内存里直接对地址的引用,这样就可以通过地址直接访问Singleton类型了)。接下来是初始化过程,首先调用sin的构造方法,然后将counter1、counter2分别+1,即counter1 = 1,counter2 = 1,完成了sin静态变量的初始化,然后初始化静态变量counter1,但是由于没有对counter1赋初值,所以counter1还是为1,然而,程序中对counter2进行了赋初值操作,即将counter2赋值为0。这样便完成了类型的初始化,得到的counter1和counter2的结果为1和0,分析完毕。


  结果分析流程图如下:


image.png


②同理也可以对测试二进行结果分析


四、总结


  整个类的初始化三个阶段细节过程远比这个复杂得多,但是我们仍可以通过类的整个宏观流程来分析出正确的结果,对过程的分析也有助于我们写出正确的程序。真正做到知其然知其所以然。也感谢各位园友的观看,谢谢。

目录
相关文章
|
4月前
|
安全 前端开发 Java
【JVM的秘密揭秘】深入理解类加载器与双亲委派机制的奥秘!
【8月更文挑战第25天】在Java技术栈中,深入理解JVM类加载机制及其双亲委派模型是至关重要的。JVM类加载器作为运行时系统的关键组件,负责将字节码文件加载至内存并转换为可执行的数据结构。其采用层级结构,包括引导、扩展、应用及用户自定义类加载器,通过双亲委派机制协同工作,确保Java核心库的安全性与稳定性。本文通过解析类加载器的分类、双亲委派机制原理及示例代码,帮助读者全面掌握这一核心概念,为开发更安全高效的Java应用程序奠定基础。
93 0
|
3月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
100 35
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
2月前
|
缓存 前端开发 Java
JVM知识体系学习二:ClassLoader 类加载器、类加载器层次、类过载过程之双亲委派机制、类加载范围、自定义类加载器、编译器、懒加载模式、打破双亲委派机制
这篇文章详细介绍了JVM中ClassLoader的工作原理,包括类加载器的层次结构、双亲委派机制、类加载过程、自定义类加载器的实现,以及如何打破双亲委派机制来实现热部署等功能。
53 3
|
3月前
|
Arthas Java 测试技术
JVM —— 类加载器的分类,双亲委派机制
类加载器的分类,双亲委派机制:启动类加载器、扩展类加载器、应用程序类加载器、自定义类加载器;JDK8及之前的版本,JDK9之后的版本;什么是双亲委派模型,双亲委派模型的作用,如何打破双亲委派机制
JVM —— 类加载器的分类,双亲委派机制
|
2月前
|
前端开发 Java 应用服务中间件
JVM进阶调优系列(1)类加载器原理一文讲透
本文详细介绍了JVM类加载机制。首先解释了类加载器的概念及其工作原理,接着阐述了四种类型的类加载器:启动类加载器、扩展类加载器、应用类加载器及用户自定义类加载器。文中重点讲解了双亲委派机制,包括其优点和缺点,并探讨了打破这一机制的方法。最后,通过Tomcat的实际应用示例,展示了如何通过自定义类加载器打破双亲委派机制,实现应用间的隔离。
|
7月前
|
前端开发 安全 Java
深入浅出JVM(八)之类加载器
深入浅出JVM(八)之类加载器
|
4月前
|
数据库 C# 开发者
WPF开发者必读:揭秘ADO.NET与Entity Framework数据库交互秘籍,轻松实现企业级应用!
【8月更文挑战第31天】在现代软件开发中,WPF 与数据库的交互对于构建企业级应用至关重要。本文介绍了如何利用 ADO.NET 和 Entity Framework 在 WPF 应用中访问和操作数据库。ADO.NET 是 .NET Framework 中用于访问各类数据库(如 SQL Server、MySQL 等)的类库;Entity Framework 则是一种 ORM 框架,支持面向对象的数据操作。文章通过示例展示了如何在 WPF 应用中集成这两种技术,提高开发效率。
63 0
|
4月前
|
开发者 C# Windows
WPF布局大揭秘:掌握布局技巧,轻松创建响应式用户界面,让你的应用程序更上一层楼!
【8月更文挑战第31天】在现代软件开发中,响应式用户界面至关重要。WPF(Windows Presentation Foundation)作为.NET框架的一部分,提供了丰富的布局控件和机制,便于创建可自动调整的UI。本文介绍WPF布局的基础概念与实现方法,包括`StackPanel`、`DockPanel`、`Grid`等控件的使用,并通过示例代码展示如何构建响应式布局。了解这些技巧有助于开发者优化用户体验,适应不同设备和屏幕尺寸。
101 0
|
4月前
|
安全 前端开发 Java
【JVM 探秘】ClassLoader 类加载器:揭秘 Java 类加载机制背后的秘密武器!
【8月更文挑战第25天】本文全面介绍了Java虚拟机(JVM)中的类加载器,它是JVM的核心组件之一,负责将Java类加载到运行环境中。文章首先概述了类加载器的基本工作原理及其遵循的双亲委派模型,确保了核心类库的安全与稳定。接着详细阐述了启动、扩展和应用三种主要类加载器的层次结构。并通过一个自定义类加载器的例子展示了如何从特定目录加载类。此外,还介绍了类加载器的完整生命周期,包括加载、链接和初始化三个阶段。最后强调了类加载器在版本隔离、安全性和灵活性方面的重要作用。深入理解类加载器对于掌握JVM内部机制至关重要。
163 0
|
5月前
|
存储 前端开发 Java
(二)JVM成神路之剖析Java类加载子系统、双亲委派机制及线程上下文类加载器
上篇《初识Java虚拟机》文章中曾提及到:我们所编写的Java代码经过编译之后,会生成对应的class字节码文件,而在程序启动时会通过类加载子系统将这些字节码文件先装载进内存,然后再交由执行引擎执行。本文中则会对Java虚拟机的类加载机制以及执行引擎进行全面分析。