文档章节

【深入Java虚拟机】之三:类初始化

侠客人生
 侠客人生
发布于 2017/07/25 14:14
字数 1335
阅读 5
收藏 0
点赞 0
评论 0

    类初始化是类加载过程的最后一个阶段,到初始化阶段,才真正开始执行类中的Java程序代码。虚拟机规范严格规定了有且只有四种情况必须立即对类进行初始化:

 

  • 遇到new、getstatic、putstatic、invokestatic这四条字节码指令时,如果类还没有进行过初始化,则需要先触发其初始化。生成这四条指令最常见的Java代码场景是:使用new关键字实例化对象时、读取或设置一个类的静态字段(static)时(被static修饰又被final修饰的,已在编译期把结果放入常量池的静态字段除外)、以及调用一个类的静态方法时。
  • 使用Java.lang.refect包的方法对类进行反射调用时,如果类还没有进行过初始化,则需要先触发其初始化。
  • 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
  • 当虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先执行该主类。

    虚拟机规定只有这四种情况才会触发类的初始化,称为对一个类进行主动引用,除此之外所有引用类的方式都不会触发其初始化,称为被动引用。下面举一些例子来说明被动引用。

 

    1、通过子类引用父类中的静态字段,这时对子类的引用为被动引用,因此不会初始化子类,只会初始化父类

 

[java] view plain copy

  1. class Father{  
  2.     public static int m = 33;  
  3.     static{  
  4.         System.out.println("父类被初始化");  
  5.     }  
  6. }  
  7.   
  8. class Child extends Father{  
  9.     static{  
  10.         System.out.println("子类被初始化");  
  11.     }  
  12. }  
  13.   
  14. public class StaticTest{  
  15.     public static void main(String[] args){  
  16.         System.out.println(Child.m);  
  17.     }  
  18. }  

    执行后输出的结果如下:

 

    父类被初始化
    33

    对于静态字段,只有直接定义这个字段的类才会被初始化,因此,通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。

 

    2、常量在编译阶段会存入调用它的类的常量池中,本质上没有直接引用到定义该常量的类,因此不会触发定义常量的类的初始化

 

[java] view plain copy

  1. class Const{  
  2.     public static final String NAME = "我是常量";  
  3.     static{  
  4.         System.out.println("初始化Const类");  
  5.     }  
  6. }  
  7.   
  8. public class FinalTest{  
  9.     public static void main(String[] args){  
  10.         System.out.println(Const.NAME);  
  11.     }  
  12. }  

    执行后输出的结果如下:

 

    我是常量

    虽然程序中引用了const类的常量NAME,但是在编译阶段将此常量的值“我是常量”存储到了调用它的类FinalTest的常量池中,对常量Const.NAME的引用实际上转化为了FinalTest类对自身常量池的引用。也就是说,实际上FinalTest的Class文件之中并没有Const类的符号引用入口,这两个类在编译成Class文件后就不存在任何联系了。

 

    3、通过数组定义来引用类,不会触发类的初始化

 

[java] view plain copy

  1. class Const{  
  2.     static{  
  3.         System.out.println("初始化Const类");  
  4.     }  
  5. }  
  6.   
  7. public class ArrayTest{  
  8.     public static void main(String[] args){  
  9.         Const[] con = new Const[5];  
  10.     }  
  11. }  

    执行后不输出任何信息,说明Const类并没有被初始化。

 

    但这段代码里触发了另一个名为“LLConst”的类的初始化,它是一个由虚拟机自动生成的、直接继承于java.lang.Object的子类,创建动作由字节码指令newarray触发,很明显,这是一个对数组引用类型的初初始化,而该数组中的元素仅仅包含一个对Const类的引用,并没有对其进行初始化。如果我们加入对con数组中各个Const类元素的实例化代码,便会触发Const类的初始化,如下:

 

[java] view plain copy

  1. class Const{  
  2.     static{  
  3.         System.out.println("初始化Const类");  
  4.     }  
  5. }  
  6.   
  7. public class ArrayTest{  
  8.     public static void main(String[] args){  
  9.         Const[] con = new Const[5];  
  10.         for(Const a:con)  
  11.             a = new Const();  
  12.     }  
  13. }  

    这样便会得到如下输出结果:

 

    初始化Const类
    根据四条规则的第一条,这里的new触发了Const类。

 

    最后看一下接口的初始化过程与类初始化过程的不同。

    接口也有初始化过程,上面的代码中我们都是用静态语句块来输出初始化信息的,而在接口中不能使用“static{}”语句块,但编译器仍然会为接口生成<clinit>类构造器,用于初始化接口中定义的成员变量(实际上是static final修饰的全局常量)。

   二者在初始化时最主要的区别是:当一个类在初始化时,要求其父类全部已经初始化过了,但是一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候(如引用接口中定义的常量),才会初始化该父接口。这点也与类初始化的情况很不同,回过头来看第2个例子就知道,调用类中的static final常量时并不会 触发该类的初始化,但是调用接口中的static final常量时便会触发该接口的初始化。

本文转载自:http://blog.csdn.net/ns_code/article/details/17845821

共有 人打赏支持
侠客人生
粉丝 14
博文 43
码字总数 82954
作品 0
朝阳
Java类加载及变量初始化过程

Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就是解决上面3个问题的。 本文前...

kalo
2014/09/29
0
0
面试中关于Java虚拟机(jvm)的问题看这篇就够了

最近看书的过程中整理了一些面试题,面试题以及答案都在我的文章中有所提到,希望你能在以问题为导向的过程中掌握虚拟机的核心知识。面试毕竟是面试,核心知识我们还是要掌握的,加油~~~ 下面...

snailclimb
05/12
0
0
Java虚拟机运行时数据区结构

本文部分参考自《Java虚拟机规范(Java SE 7版)》的中译本和周志明的《深入理解Java虚拟机》,另加个人理解。原书对Java虚拟机运行时数据区描述只有6页,同时参考其他网络网资料,个人能力所...

foodon
2014/12/09
0
4
JVM学习笔记一:类加载机制介绍

在代码编译后,就会生成JVM(Java虚拟机)能够识别的二进制字节流文件(*.class)。而JVM把Class文件中的类描述数据从文件加载到内存,并对数据进行校验、转换解析、初始化,使这些数据最终成...

刘祖鹏
07/17
0
0
Java虚拟机类加载和执行机制

虚拟机的类加载和执行机制是虚拟机的最主要功能,在这里简单的对所知的内容进行一次温习,并记录以方便日后重温。 本篇主要引用《深入理解Java虚拟机——JVM高级特性与最佳实践》一书。 1、类...

forest13
2013/10/05
0
1
《深入理解Java虚拟机》之类加载机制(6)

java语言是一种编译后再经过解释器执行的过程, 解释器主要就是如何处理解释Class文件的二进制字节流。JVM主要包含三大核心部分:运行时数据区,类加载器和执行引擎。 虚拟机将描述类的数据从...

lixiyuan
2014/04/11
0
0
结合Java数据类型分析JVM运行时数据结构

阅读建议:本博客基于《Java编程思想》、《深入理解Java虚拟机》、《java并发编程实战》三本Java书籍和面试中遇到的问题而做的总结。 JVM(JAVA Virtual Machine Java虚拟机)运行时数据区域:...

硕士鸭
2017/10/19
0
0
Java语言中单例模式的四种写法

作为设计模式理论中的Helloworld,相信学习java语言的人,都应该听说过单例模式。单例模式作为对象的一种创建模式,它的作用是确保某一个类在整个系统中只有一个实例,而且自行实例化并向整个...

相见欢
2013/02/03
0
20
linux web篇---之三--tomcat

一、java概述 1、java的四个独立却又相关的技术: java程序设计语言: java源程序 java API: 以连接java的库文件,官方提供很多库文件,以提高java的开发速度,通过API连接到相应的库文件。...

kuang_hp
07/04
0
0
《深入理解Java虚拟机》读书笔记

《深入理解Java虚拟机》读书笔记 堆分配参数: -XX:+PrintGC 使用该参数,虚拟机启动后,只要遇到GC就会打印日志; -XX:+UseSerialGC 配置串行回收器; -XX:+PrintGCDeltails 可以查看详细...

卯金刀GG
2017/11/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android 复制和粘贴功能

做了一回搬运工,原文地址:https://blog.csdn.net/kennethyo/article/details/76602765 Android 复制和粘贴功能,需要调用系统服务ClipboardManager来实现。 ClipboardManager mClipboardM...

她叫我小渝
15分钟前
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
32分钟前
4
0
jQuery零基础入门——(六)修改DOM结构

《jQuery零基础入门》系列博文是在廖雪峰老师的博文基础上,可能补充了个人的理解和日常遇到的点,用我的理解表述出来,主干出处来自廖雪峰老师的技术分享。 在《零基础入门JavaScript》的时...

JandenMa
49分钟前
0
0
linux mint 1.9 qq 安装

转: https://www.jianshu.com/p/cdc3d03c144d 1. 下载 qq 轻聊版,可在百度搜索后下载 QQ7.9Light.exe 2. 去wine的官网(https://wiki.winehq.org/Ubuntu) 安装 wine . 提醒网页可以切换成中...

Canaan_
今天
0
0
PHP后台运行命令并管理运行程序

php后台运行命令并管理后台运行程序 class ProcessModel{ private $pid; private $command; private $resultToFile = ''; public function __construct($cl=false){......

colin_86
今天
1
0
数据结构与算法4

在此程序中,HighArray类中的find()方法用数据项的值作为参数传递,它的返回值决定是否找到此数据项。 insert()方法向数组下一个空位置放置一个新的数据项。一个名为nElems的字段跟踪记录着...

沉迷于编程的小菜菜
今天
1
1
fiddler安装和基本使用以及代理设置

项目需求 由于开发过程中客户端和服务器数据交互非常频繁,有时候服务端需要知道客户端调用接口传了哪些参数过来,这个时候就需要一个工具可以监听这些接口请求参数,已经接口的响应的数据,这种...

银装素裹
今天
0
0
Python分析《我不是药神》豆瓣评论

读取 Mongo 中的短评数据,进行中文分词 对分词结果取 Top50 生成词云 生成词云效果 看来网上关于 我不是药神 vs 达拉斯 的争论很热啊。关于词频统计就这些,代码中也会完成一些其它的分析任...

猫咪编程
今天
0
0
虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
昨天
1
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部