Java虚拟机之类加载的示例分析

  介绍

小编给大家分享一下Java虚拟机之类加载的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!

Java是什么

Java是一门面向对象编程语言,可以编写桌面应用程序,网络应用程序,分布式系统和嵌入式系统应用程序。

一、类加载流程

类加载的流程可以简单分为三步:

<李>

加载

<李>

连接

<李>

初始化

而其中的连接又可以细分为三步:

<李>

验证

<李>

准备

<李>

解析

下面会分别对各个流程进行介绍。

1.1类加载条件

在了解类接在流程之前,先来看一下触发类加载的条件。

<代码> JVM> <李>

创建一个类的实例的时候,比如使用新<代码> 创建,或者使用反射,克隆,反序列化

<李>

调用类的静态方法的时候,比如使用<代码> invokestatic> <李>

使用类或接口的静态字段:比如使用<代码> getstatic <代码>//<代码> putstatic> <李>

使用<代码>数组> <李>

初始化子类时,要求先初始化父类

<李>

含有<代码>主要()方法的类

除了以上情况外,其他情况属于被动使用,不会引起类的初始化。

比如下面的例子:

public  class  Main  {   ,,,public  static  void  main (String [], args) {   ,,,,,,,System.out.println (Child.v);   ,,,}   }      父{class    静态{,,,   ,,,,,,,System.out.println (“Parent  init");   ,,,}   ,,,public  static  int  v =, 100;   }      class  Child  extends 父母{   ,,,static  {   ,,,,,,,System.out.println (“Child  init");   ,,,}   }

输出如下:

父init
100

而加上类加载参数<代码> - xx: + TraceClassLoading> 孩子确实被加载了:

0.068 [s] [info ,,)(类、负载),com.company.Main   [0.069][info ,,)(类、负载),com.company.Parent   [0.069][info ,,)(类、负载),com.company.Child   Parent 初始化   100年

但是并没有进行初始化。另外一个例子是关于<代码> 的,代码如下:

public  class  Main  {   ,,,public  static  void  main (String [], args) {   ,,,,,,,System.out.println (Test.STR);   ,,,}   }      测试{class    静态{,,,   ,,,,,,,System.out.println (“Test  init");   ,,,}   ,,,public  static  final  String  STR =,“Hello";   }

输出如下:

[0.066] [info ,][类、负载]com.company.Main
你好

<代码> 测试类根本没有被加载,因为最终<代码> 被做了优化,编译后的<代码> Main.class 中,并没有引用<代码> 测试类:

0:, getstatic ,,,, 2,,,,,,,,,,,,,,,,,,//, Field  java/lang/system . out: Ljava/io/PrintStream;   3:,ldc ,,,,,,,,,, # 4,,,,,,,,,,,,,,,,,,//String ,你好   5:,invokevirtual  # 5,,,,,,,,,,,,,,,,,,//, Method  java/io/PrintStream.println: (Ljava/lang/String;)V

在字节码偏移3的位置,通过<代码> ldc> # 3,=, Class ,,,,,,,,,,,,, # 24,,,,,,,,,,,,//;com/company/Test   # 4,=,String ,,,,,,,,,,,, 25号,,,,,,,,,,,,//,你好   # 5,=,Methodref ,,,,,,,,, # 26。# 27,,,,,,,,//, java/io/PrintStream.println: (Ljava/lang/String;) V

因此并没有对<代码> 测试类进行加载,只是直接引用常量池中的常量,因此输出没有<代码> 测试的加载日志。

1.2加载

类加载的时候,JVM <代码> 必须完成以下操作:

<李>

通过类的全名获取二进制数据流

<李>

解析类的二进制数据流为方法区内的数据结构

<李>

Java虚拟机之类加载的示例分析