虚拟机类加载机制(六)类初始化的过程

我们写在static块中的代码,对static变量进行的赋值,最终都会在类的初始化中进行,本来这里是没有必要写文章的

但是Java为了保证初始化工作只进行一次,对多线程下的初始化方法《clinit()》(这里应该使用尖括号的,但是csdn不知道为什么,用尖括号会出现错误,因此使用书名号代替)

方法进行了同步和加锁,所以如果在静态块中进行费时操作,会导致其他线程被阻塞式等待

而这一切都是隐性的,很难排查,所以还是有必要写一篇文章的

将一段包含静态块和静态变量赋值的类Javap反编译
源代码

public class Test{
    static {
        System.out.println("test");
    }
    static String s="test";
    public static void main(String[] args)  {
    }
}

反编译后(节选clinit方法)

static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=2, locals=0, args_size=0
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String test
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: ldc           #3                  // String test
        10: putstatic     #5                  // Field s:Ljava/lang/String;
        13: return
      LineNumberTable:
        line 3: 0
        line 5: 8

可以看出,我们打印字符串的操作,还有给静态变量赋值的操作,均被放在了clinit方法中

下面我们在static块中执行一些耗时的操作

public class Test implements Runnable{
    static {
        if(true) {
            System.out.println(Thread.currentThread().getName()+"进入static块中");
            for (; ; ) {
            }
        }
    }
    public static void main(String[] args)  {
        new Thread(new Test(),"1").start();
        new Thread(new Test(),"2").start();
        new Thread(new Test(),"3").start();
        new Thread(new Test(),"4").start();
    }

    @Override
    public void run() {
			System.out.println(Thread.currentThread().getName()+"开始执行线程");
    }
}

在这里插入图片描述
由于jvm虚拟机会自动加载main方法所在的类,main线程进入了static,而1到4线程全部被阻塞住,等待static完成

所以尽量不要在多线程情况下在static中进行过于复杂的操作

下面是clinit()的一些补充说明

  1. clinit()并不是必须的,如果没有静态块或者对静态变量赋值,clinit()是可以不生成的
  2. 接口中同样可能生成clinit()方法,因为接口中虽然不能使用static块,但是可以进行赋值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值