详谈jvm--Java中init和clinit的区别

 更新时间:2017年10月09日 10:03:54   作者:HankingHu  
下面小编就为大家带来一篇详谈jvm--Java中init和clinit的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

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类型的常量,因此在准备阶段就已经初始化话。

以上这篇详谈jvm--Java中init和clinit的区别就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java Socket实现简单模拟HTTP服务器

    java Socket实现简单模拟HTTP服务器

    这篇文章主要介绍了java Socket实现简单模拟HTTP服务器,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • 【Java】BigDecimal实现加减乘除运算代码

    【Java】BigDecimal实现加减乘除运算代码

    本篇文章主要介绍了【Java】BigDecimal实现加减乘除运算代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • 解析JPA的视图查询问题

    解析JPA的视图查询问题

    这篇文章主要是对JPA的视图查询问题进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • SpringBoot高级配置之临时属性、配置文件、日志、多环境配置详解

    SpringBoot高级配置之临时属性、配置文件、日志、多环境配置详解

    这篇文章主要介绍了SpringBoot高级配置之临时属性、配置文件、日志、多环境配置,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • SpringSecurity框架下实现CSRF跨站攻击防御的方法

    SpringSecurity框架下实现CSRF跨站攻击防御的方法

    CSRF是一种网络攻击方式,也可以说是一种安全漏洞,这种安全漏洞在web开发中广泛存在。这篇文章主要介绍了SpringSecurity框架下实现CSRF跨站攻击防御,需要的朋友可以参考下
    2019-12-12
  • idea中加入git版本控制的方法及步骤详解

    idea中加入git版本控制的方法及步骤详解

    在idea中加入git版本控制,方便团队中多人协同开发,项目可以同时方便进行管理和迭代。下面就是idea中加入git 的方法和步骤,感兴趣的朋友一起看看吧
    2021-09-09
  • spring mvc中注解@ModelAttribute的妙用分享

    spring mvc中注解@ModelAttribute的妙用分享

    这篇文章主要给大家介绍了关于spring mvc中注解@ModelAttribute妙用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Android具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-09-09
  • 命令行使用支持断点续传的java多线程下载器

    命令行使用支持断点续传的java多线程下载器

    java命令行下载器,支持断点续传下载,多线程下载,需要的朋友可以参考下
    2014-02-02
  • idea2020.2卡死在reading maven projects

    idea2020.2卡死在reading maven projects

    这篇文章主要介绍了idea2020.2卡死在reading maven projects,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 浅谈java中异常抛出后代码是否会继续执行

    浅谈java中异常抛出后代码是否会继续执行

    这篇文章主要给大家介绍了java中异常抛出后代码是否会继续执行,文章通过几种情况的代码示例给大家详细分析了这个情况,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-10-10

最新评论