java执行顺序之深入理解clinit和init
原文地址:https://blog.csdn.net/qq_36522306/article/details/80582758
前言:
最近研究了深入理解JVM这本书中的知识,对java中各部分执行的顺序有了比较深入的了解。首先我们得了解一下java中init和clinit的区别。
概念:
类型初始化方法<clinit>:JVM通过Classload进行类型加载时,如果在加载时需要进行类型初始化操作时,则会调用类型的初始化方法。类型初始化方法主要是对static变量进行初始化操作,对static域和static代码块初始化的逻辑全部封装在<clinit>方法中。
java.lang.Class.forName(String name, boolean initialize,ClassLoader loader),其中第二个参数就是是否需要初始化。
Java类型初始化过程中对static变量的初始化操作依赖于static域和static代码块的前后关系,static域与static代码块声明的位置关系会导致java编译器生成<clinit>方法字节码。类型的初始化方法<clinit>只在该类型被加载时才执行,且只执行一次。
对象实例化方法<init>:Java对象在被创建时,会进行实例化操作。该部分操作封装在<init>方法中,并且子类的<init>方法中会首先对父类<init>方法的调用。Java对象实例化过程中对实例域的初始化赋值操作全部在<init>方法中进行,<init>方法显式的调用父类的<init>方法,实例域的声明以及实例初始化语句块同样的位置关系会影响编译器生成的<init>方法的字节码顺序,<init>方法以构造方法作为结束。
下面引用自:https://blog.csdn.net/u013309870/article/details/72975536
init和clinit区别:
①init和clinit方法执行时机不同
init是对象构造器方法,也就是说在程序执行 new 一个对象调用该对象类的 constructor 方法时才会执行init方法,而clinit是类构造器方法,也就是在jvm进行类加载—–验证—-解析—–初始化,中的初始化阶段jvm会调用clinit方法。
②init和clinit方法执行目的不同
init is the (or one of the) constructor(s) for the instance, and non-static field initialization.
clinit are the static initialization blocks for the class, and static field initialization.
上面这两句是Stack Overflow上的解析,很清楚init是instance实例构造器,对非静态变量解析初始化,而clinit是class类构造器对静态变量,静态代码块进行初始化。看看下面的这段程序就很清楚了。
class X { static Log log = LogFactory.getLog(); // <clinit> private int x = 1; // <init> X(){ // <init> } static { // <clinit> } }
clinit详解
在准备阶段,变量已经赋过一次系统要求的初始值,而在初始化阶段,则根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程。
①<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{}块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问如下代码
public class Test{ static{ i=0;//给变量赋值可以正常编译通过 System.out.print(i);//这句编译器会提示"非法向前引用" } static int i=1; }
②虚拟机会保证在子类的<clinit>()方法执行之前,父类的<clinit>()方法已经执行完毕。 因此在虚拟机中第一个被执行的<clinit>()方法的类肯定是java.lang.Object。由于父类的<clinit>()方法先执行,也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作,如下代码中,字段B的值将会是2而不是1。
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); } }
- ③接口中不能使用静态语句块,但仍然有变量初始化的赋值操作,因此接口与类一样都会生成<clinit>()方法。 但接口与类不同的是,执行接口的<clinit>()方法不需要先执行父接口的<clinit>()方法。 只有当父接口中定义的变量使用时,父接口才会初始化。 另外,接口的实现类在初始化时也一样不会执行接口的<clinit>()方法。
注意:接口中的属性都是static final类型的常量,因此在准备阶段就已经初始化话。
<script>
(function(){
function setArticleH(btnReadmore,posi){
var winH = $(window).height();
var articleBox = $("div.article_content");
var artH = articleBox.height();
if(artH > winH*posi){
articleBox.css({
'height':winH*posi+'px',
'overflow':'hidden'
})
btnReadmore.click(function(){
if(typeof window.localStorage === "object" && typeof window.csdn.anonymousUserLimit === "object"){
if(!window.csdn.anonymousUserLimit.judgment()){
window.csdn.anonymousUserLimit.Jumplogin();
return false;
}else if(!currentUserName){
window.csdn.anonymousUserLimit.updata();
}
}
articleBox.removeAttr("style");
$(this).parent().remove();
})
}else{
btnReadmore.parent().remove();
}
}
var btnReadmore = $("#btn-readmore");
if(btnReadmore.length>0){
if(currentUserName){
setArticleH(btnReadmore,3);
}else{
setArticleH(btnReadmore,1.2);
}
}
})()
</script>
</article>
java执行顺序之深入理解clinit和init的更多相关文章
- 【原创】Junit4详解二:Junit4 Runner以及test case执行顺序和源代码理解
概要: 前一篇文章我们总体介绍了Junit4的用法以及一些简单的测试.之前我有个疑惑,Junit4怎么把一个test case跑起来的,在test case之前和之后我们能做些什么? Junit4执行 ...
- java执行顺序
本文讨论Java中(静态)变量.(静态)代码块的执行顺序 首先创建3个类: 1.Foo类,用于打印变量 public class Foo { public Foo(String word) { Sys ...
- junit4X系列源码--Junit4 Runner以及test case执行顺序和源代码理解
原文出处:http://www.cnblogs.com/caoyuanzhanlang/p/3534846.html.感谢作者的无私分享. 前一篇文章我们总体介绍了Junit4的用法以及一些简单的测试 ...
- 一条sql语句搞定基于mysql的sql执行顺序的基本理解
对数据库基本操作是每个程序员基本功,如何理解并快速记住sql执行的顺序呢,其实一条复杂的sql就能搞定: SELECT DISTINCT <select_list> FROM <le ...
- 关于Unity物理事件的执行顺序的最新理解
物体A: public class A:{ B b; void FixedUpdate(){ if(input.GetKeyDow(Keycode.I)) { collider.enable=fals ...
- 高手总结的CSS执行顺序及其优先权问题汇总
今天在看一本书时又看到了”CSS优 先权“这个问题,感觉这个问题还是比较重要的,也算是样式的特异性吧,尤其是在面对较多.较深层.较复杂的样式属性时,理解CSS的加权计算方法对于重写 样式属性之类的问题 ...
- SQL语句中各个部分的执行顺序(转)
原文链接:http://www.tuicool.com/articles/fERNv2 写在前面的话:有时不理解SQL语句各个部分执行顺序,导致理解上出现偏差,或者是书写SQL语句时随心所欲,所以有必 ...
- ASP.NET Page执行顺序【转】
一.ASP.NET 母版页和内容页中的事件 母版页和内容页都可以包含控件的事件处理程序.对于控件而言,事件是在本地处理的,即内容页中的控件在内容页中引发事件,母版页中的控件在母版页中引发事件.控件事件 ...
- Spring filter和拦截器(Interceptor)的区别和执行顺序
转载自:http://listenup.iteye.com/blog/1559553 1.Filter过滤器只过滤jsp文件不过滤action请求解决方案 解决办法:在web.xml中将filter的 ...
随机推荐
- 【NOI2019模拟2019.6.29】组合数(Lucas定理、数位dp)
Description: p<=10且p是质数,n<=7,l,r<=1e18 题解: Lucas定理: \(C_{n}^m=C_{n~mod~p}^{m~mod~p}*C_{n/p} ...
- java poi导出Excel合并单元格并设置边框
import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; i ...
- linux IPC的PIPE
一.PIPE(无名管道) 函数原型: #include <unistd.h> ]); 通常,进程会先调用pipe,接着调用fork,从而创建从父进程到子进程的IPC通道. 父进程和子进程之 ...
- K8S 容器之间通讯方式
概述 首先k8s里面容器是存在于pod里面的,所以容器之间通讯,一般分为三种类型: 1. pod内部容器之间 2. pod 与 pod 容器之间 3. pod 访问service服务 pod内部容器之 ...
- BZOJ 2326: [HNOI2011]数学作业(矩阵乘法)
传送门 解题思路 NOIp前看到的一道题,当时想了很久没想出来,NOIp后拿出来看竟然想出来了.注意到有递推\(f[i]=f[i-1]*poww[i]+i\),\(f[i]\)表示\(1-i\)连接起 ...
- flask json
导入 from flask import Flask,jsonify 1.列表 def index(): arr=['mkdir','md','touch'] return jsonify(arr) ...
- ocaml学习
ocaml与haskell一样,是functional programming的代表. 对于有一定编程经验的人来说,入手一种新语言,最有效的方式就是开发一些实用的utility,因此top-level ...
- ubuntu 无pthread
由于学习多线程编程,所以用到pthread,但是man的时候却发现没有pthread函数库的手册页,然后安装 $sudo apt-get install glibc-doc 安装以后,发现还是有很多函 ...
- 4-Ubuntu-启动/关闭/重启mysql服务
启动: sudo service mysql start 关闭: sudo service mysql stop 重启: sudo service mysql restart
- 2014 ACM-ICPC Vietnam National First Round
Contest Link easy: ABDGIJ medium-easy: E medium: H medium-hard: CF A. Cool number 各数位之和不大,枚举即可. E. B ...