JVM类加载(3)—初始化
3、初始化
在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量(静态变量)和其他资源,或者从另外一个角度表达:初始化过程是执行类构造器<client>()方法的过程。<client>()方法:
- <client>()方法是由编译器自动收集类中的所有类变量(静态变量)的赋值动作和静态语句块(static{})中的语句合并吃产生的,编译器收集的顺序是由语句在源文件中出现的顺序决定的,静态语句块只能访问到定义在静态语句块之前的变量,定义在它之后的变量,静态语句块能进行赋值操作,但是不能进行访问。
public class Test {
static{
i = 0; //这句能编译通过
System.out.println(i); //这里编译会报错,提示“非法向前引用”
}
static int i;
}
- <client>()方法与类的构造函数不同,它不需要显式的调用父类构造器,虚拟机会保证在<client>()方法执行之前,父类的<client>()方法已经执行完毕。因此在虚拟机中第一个被执行的<client>()方法肯定是java.lang.Object的<client>()方法。
- 由于父类的<client>()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作,如下代码,字段B的值会是2而不会是1
public class Test {
static class Parent{
public static int A = 1;
static{
A = 2;
}
} static class Sub extends Parent{
public static int B = A;
} public static void main(String[] args) {
System.out.println(Sub.B);
}
}
- <client>()方法对于类或接口来说并不是必需的,如果一个类中没有静态语句块,也没有静态变量的赋值操作,那么编译器可以不为这个类生成<client>()方法。
- 接口中不能使用静态语句块,但仍然有变量赋值初始化的操作,因此接口和类一样都会生成<client>()方法。但接口与类不同的是,执行接口的<client>()方法不需要执行父接口的<client>()方法,只有当父接口定义的变量被使用时父接口才会初始化。另外接口的实现进行初始化时,也不会执行接口的<client>()方法,同理除非访问了接口中定义的静态变量才会初始化接口。如果通过子类访问定义在父类中的静态变量时,只有父类会被初始化,子类则不会被初始化,如下代码清单:
class Parent {
public static int A = 1;
static {
System.out.println("this is parent");
}
} class Sub extends Parent {
public static int B = 2;
static {
System.out.println("this is Sub");
}
} public class Test {
public static void main(String[] args) {
int i = Sub.A;
}
}
// output:
// this is parent - 虚拟机会保证一个类的<client>()方法在多线程环境中被正确的加锁、同步,如果多个线程去初始化一个类,那么只会有一个线程去执行这个类的<client>()方法,其他线程都需要阻塞等待,直到活动线程的<client>()方法执行完毕。如果一个类的<client>()方法有耗时很长的操作,就能造成多个进程阻塞,在实际应用中,这种阻塞往往是很隐蔽的。同一个虚拟机上类的<client>()方法只会执行一次。
- 编译时的常量访问不会对该类进行初始化,如果只有在运行时才能确定,则会执行类的初始化动作,如下代码:
import java.util.Random; class Init{
static final int x = 6 / 3;
static final int y = new Random().nextInt(100);
static{
System.out.println("init----");
}
} public class Test {
public static void main(String[] args) {
System.out.println(Init.x); //此处Init类不会进行初始化
System.out.println(Init.y); //执行这条语句时,Init类才进行初始化
}
}
// output:
//2
//init----
//
类只有在被首次主动使用时,才进行初始化,类的主动使用方式:
(1)、实例化一个类,new一个类的实例对象
(2)、访问类的静态变量
(3)、调用类的静态方法
(4)、通过反射调用类
(5)、实例化类的子类
(6)、被标位启动类的类
Java虚拟机执行类的初始化语句为类赋予初始值,在程序中静态变量初始化有两种方式
(1)、在变量声明处初始化
(2)、在静态代码块中进行初始化
private static int param1 = 1;//变量声明时初始化
private static int param2;
static{
param2 = 2; //静态代码块中进行初始化
}
针对private static int param1 = 1;在连接阶段的准备阶段时,param1变量被赋予int变量初始值0,在初始化阶段执行赋值操作,赋值为1。
JVM类加载(3)—初始化的更多相关文章
- Java 类加载与初始化
Java系列笔记(1) - Java 类加载与初始化 目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理 ...
- JVM类加载过程学习总结
JVM类加载过程学习总结 先不说JVM类加载的原理,先看实例: NormalTest类,包含了一个静态代码块,执行的任务就是打印一句话. /** * 在正常类加载条件下,看静态代码块是否会执行 * @ ...
- JVM类加载续
上一篇理解了JVM类加载过程的第一个阶段,这篇来说说剩下的阶段:验证.准备.解析.初始化.需要注意的是,这些阶段(解析除外)只是按照这个顺序开始,但是执行的过程中可能存在交叉. 验证:就是要对加载的二 ...
- 【转载】Java系列笔记(1) - Java 类加载与初始化
Java系列笔记(1) - Java 类加载与初始化 原文地址:http://www.cnblogs.com/zhguang/p/3154584.html 目录 类加载器 动态加载 链接 初始化 示例 ...
- JVM类加载机制以及类缓存问题的处理
一:JVM类加载机制 和 类缓存问题的处理 当一个java项目启动的时候,JVM会找到main方法,根据对象之间的调用来对class文件和所引用的jar包中的class文件进行加载(其步骤分为加载.验 ...
- JVM基础系列第7讲:JVM 类加载机制
当 Java 虚拟机将 Java 源码编译为字节码之后,虚拟机便可以将字节码读取进内存,从而进行解析.运行等整个过程,这个过程我们叫:Java 虚拟机的类加载机制.JVM 虚拟机执行 class 字节 ...
- 【深入Java虚拟机】一 JVM类加载过程
首先Throws(抛出)几个自己学习过程中一直疑惑的问题: 1.什么是类加载?什么时候进行类加载? 2.什么是类初始化?什么时候进行类初始化? 3.什么时候会为变量分配内存? 4.什么时候会为变量赋默 ...
- JVM总结(四):JVM类加载机制
这一节我们来总结一下JVM类加载机制.具体目录如下: 类加载的过程 类加载过程概括 说说引用 详解类加载全过程: 加载 验证 准备 解析 初始化 虚拟机把描述类的数据从Class文件加载到内存,并对数 ...
- JVM 类加载机制详解
如下图所示,JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程. 加载 加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lan ...
- Java虚拟机(四):JVM类加载机制
1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构 ...
随机推荐
- Django多对多的创建
1.多对多创建的应用场景: 在某表中创建一行数据是,有一个可以多选的下拉框 例如:创建用户信息,需要为用户指定多个爱好 2.创建方式: 方式一:自定义关系表,手动创建一张表用于关联其他多张表的关系 c ...
- linux shell 基础 使用日志与心得
linux shell 基础 使用日志与心得 1.#!/bin/bash 第一行就出现#!/bin/bash是指此脚本使用/bin/bash来解释执行.其中,#!是一个特殊的表示符,其后,跟着解释此脚 ...
- 【LeetCode】:二叉搜索树
相关概念: 一棵二叉搜索树(BST)是以一棵二叉树来组织的,可以用链表数据结构来表示,其中,每一个结点就是一个对象,一般地,包含数据内容key和指向孩子(也可能是父母)的指针属性.如果某个孩子结点不存 ...
- StartUML如何画“不折弯”的直线
将下图中line style改成 OBlique.快捷键Ctrl +B
- flex 坐标系
全局坐标(舞台坐标) 本地坐标 内容坐标系 地图坐标(MapPoint) flash和flex针对不同的目的,提供了3种不同的坐标系 全局的就是(stage级别的) 本地坐标系(组件级别的) 内容 ...
- [原创]java WEB学习笔记18:java EE 中的MVC 设计模式(理论)
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- linux下搭建java开发环境
1 下载jdk包 这里下载.gz格式的,通过ftp上传到服务器 2 解压到指定目录,如/usr/java/ tar -xvf XXX.tar.gz 解压后会在/usr/java下生成一个目录,如jdk ...
- 剑指offer之 数组中出现次数超过一半的数字
public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array==null||array.le ...
- 在Delphi2007下安装ReportMachine6.5
如何在Delphi2007下安装ReportMachine6.5: 一.在安装ReportMachine6.5之前要安装如下组件: (1).llPdfLib3.6,用于导出PDF文件: (2).Ehl ...
- android 真心话大冒险 摇色子
android 真心话大冒险 摇色子 软件