Java技术专区-虚拟机系列-类加载机制(类的初始化)
类加载的生命周期:
加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载
加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 卸载
这6个阶段顺序是确定的,klass的加载过程一定会按照这个顺序执行。为了支持java的运行时绑定,解析阶段在某些情况下会在初始化之后才进行。
类的初始化阶段
对于
加载
这个阶段是跟具体的虚拟机实现有关,对于整个类加载阶段最重要的就是初始化
这个阶段.
JVM执行初始化的情况
对于Hotspot虚拟机而言,遇见以下这5种情况就需要进行
初始化
:遇到
new、getstatic、putstatic、invokestatic
,如果类还没进行初始化的时候就进行初始化。生成这4种指令最常见的就是:new一个实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译时吧结果放在常量池的静态字段排除),已经调用一个类的静态方法时。
- java的反射对类进行反射调用。
- 初始化类之间,检测父类是否初始化,否则先初始化父类。
- 虚拟机启动时,用户需要制定一个要执行的主类(包含main方法的类),虚拟机会先初始化这个类
- 使用jdk7以上动态语言支持时,如果一个methodHandler实例最后的解析结果
REF_getstatic、REF_putstatic、REF_invokestatic
的方法句柄,并且这个方法的句柄对应的类没有初始化的时候。
这里我们需要注意的点,上面的五种情况指的是主动的引用方式,除了上面5种主动引用之外的被动引用是不会触发初始化
的.
类的被动引用实例:
情况一:通过子类来引用父类的静态字段,是只会执行父类的初始化而子类不会初始化的,但是Hotspot虚拟机下会触发子类的加载和验证。
情况二:声明一个数组类型的类。因为jvm会调用newarray生成一个继承自object的子类,这个类代表了对应的这个类型的数组类型。
情况三:A引用了B中
final
修饰过的静态属性不会导致B的初始化,因为经过编译器的优化,A中引用的这个B的属性元素已经在编译时期存储到了A类下的常量池中,所以其实A下的引用来自于对自身常量池的引用。我们这里还需要注意的一点是接口和类不同的就是接口的父接口只有在真正被使用的时候才会被初始化
类的初始化之clinit方法
对于jvm而言,类的初始化也就是执行clinit
方法,那么什么是clinit
方法?
clinit
方法是有编译器自动收集类中的所有变量的赋值动作和静态语句块中的语句合并产生的一个用于jvm执行类的初始化的方法。
需要注意以下几点:
clinit
方法不需要显示的调用父类构造器,虚拟机会保证子类的clinit
方法执行之前父类的clinit
方法已经调用完毕,因此虚拟机中第一个被执行clinit
方法的肯定是Object
。clinit
对于类和接口不是必须的,如果类中没有静态块,也没有对变量的赋值操作,编译器可以不为这个类生产clinit
方法。执行接口的
clinit
方法不需要先执行父接口的clinit
方法,只有当父接口中定义的变量被使用,父接口才会初始化。另外接口的实现类在初始化也一样不会执行接口的clinit
方法。jvm会保证一个类的
clinit
方法在多线程环境下被正确加锁同步,也就是说类的初始化是线程安全的,同时需要注意的是,如果一个线程执行clinit
方法时有很耗时的操作,就会阻塞其他也要初始化的这个类的线程。
验证猜想的小技巧
关于我们文章上述初始化过程中,如何验证,我们可以把代码在写在类的static
块里,就能验证我买的猜想了。原理就在上文关于clinit方法中。
Java技术专区-虚拟机系列-类加载机制(类的初始化)的更多相关文章
- Java技术专区-虚拟机系列-虚拟机参数(常用)
基础参数系类(内存分配) -server:一定要作为第一个参数,在多个CPU时性能佳 -Xmn:young generation的heap大小,一般设置为Xmx的3.4分之一-Xms:初始Heap大小 ...
- Java技术专区-虚拟机系列-堆快照(获取)
1.JVM-堆快照(Snapshot) 1.1 输出方式-获取hprof文件 启动参数配置OOM时触发打印堆快照 (1)tomcat启动方式添加参数 (添加环境变量) export JAVA_OPTS ...
- java 复习整理(五 类加载机制与对象初始化)
类加载机制与对象初始化 一 . 类加载机制 类加载机制是指.class文件加载到jvm并形成Class对象的机制.之后应用可对Class对象进行实例化并调用.类加载机制可在运行时动态加载外部的类, ...
- Java虚拟机:类加载机制详解
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 大家知道,我们的Java程序被编译器编译成class文件,在class文件中描述的各种信息,最终都需要加载到虚拟机内存才能运行和使用,那么 ...
- java 虚拟机的类加载机制
Java 虚拟机的类加载机制 关于类加载机制: 虚拟机把描述类的数据从Class 文件加载到内存,并对数据进行效验.转换解析和初始化,最终 形成可以被虚拟机直接使用的Java 类型,就是虚拟机的类 ...
- java虚拟机的类加载机制
引言 我们写的代码是放在.java文件中,经过编译器编译后,转成.class文件.Class文件是一串二进制流,它可以被各平台的虚拟机所接受,实现跨平台. 虚拟机将描述类的数据从class文 ...
- 深入理解Java虚拟机(类加载机制)
文章首发于微信公众号:BaronTalk 上一篇文章我们介绍了「类文件结构」,这一篇我们来看看虚拟机是如何加载类的. 我们的源代码经过编译器编译成字节码之后,最终都需要加载到虚拟机之后才能运行.虚拟机 ...
- 【进阶之路】深入理解Java虚拟机的类加载机制(长文)
我们在参加面试的时候,经常被问到一些关于类加载机制的问题,也都会在面试之前准备的时候背好答案,但是我们是否有去深入了解什么是类加载机制呢?这段时间因为一些事情在家看了些书,这次就和大家分享一些关于Ja ...
- 深入理解Java虚拟机之类加载机制篇
概述 虚拟机把描述类的数据从 Class 文件加载到内存中,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,就是虚拟机的类加载机制. 在Java语言里面,类型的 ...
随机推荐
- 8条关于Web前端性能的优化建议
一般网站优化都是优化后台,如接口的响应时间.SQL优化.后台代码性能优化.服务器优化等.高并发情况下,对前端web优化也是非常重要的. 下面说说几种常见的优化措施. 1.HTML CSS JS位置 一 ...
- 一个spark SQL和DataFrames的故事
package com.lin.spark import org.apache.spark.sql.{Row, SparkSession} import org.apache.spark.sql.ty ...
- C++中的转换构造函数
1,类型转换函数主要功能就是做类型转换,类型转换是将一个数据从 A 类型转换 到 B 类型,有隐式类型转换和强制类型转换两种: 2,再论类型转换: 1,标准数据类型之间会进行隐式的类型安全转换: 1 ...
- 【知识强化】第四章 网络层 4.3 IP
这节课我们来学习一下IP数据报的格式.那之所以把路由算法这一小节跳过呢,就是因为我们之后会要讲到路由的选择协议.那在路由选择协议这一块讲路由算法,我觉得是比较合适的.那我们先来看一下这节课要讲的知识. ...
- 2019-9-2-win10-uwp-隐私声明
title author date CreateTime categories win10 uwp 隐私声明 lindexi 2019-09-02 12:57:38 +0800 2018-2-13 1 ...
- python时间日期处理
一.模块介绍: 1.time模块接近操作系统,模块中的大多数函数是调用了所在平台C library的同名函数,部分函数式平台相关的:基于Unix Timestamp,能表述的日期范围被限定在 1970 ...
- 【leetcode】679. 24 Game
题目如下: 解题思路:24点是非常经典的游戏了,因为本题数据量小,可以使用穷举法,把所有的可能结果都算出来.假设nums = [a,b,c,d],记f(n)表示用nums中n个数字进行运算可以得到的结 ...
- table 中 当前行变量的获取
- 【Shell】ps -ef 和ps aux
两者没太大差别 追溯到Unix系统中的两种风格,System V风格和BSD 风格,ps aux最初用到Unix Style中,而ps -ef被用在System V Style中,两者输出略有不同.现 ...
- centos下mysql密码修改与远程连接
之前的服务器,好久没上去过了,今天上去,密码居然又忘了... 要修改mysql的登陆密码,首先要设置 #vim /etc/my.cnf 在[mysqld] 下面加上一句 skip-grant-tabl ...