static static final 与 static 语句块

 

bluedavy 的一篇博客展开

· <clinit>

是由编译器收集static 字段、static 语句块生成的静态初始化方法, 虚拟机在初始化类的时候负责执行,并且父类先于子类;jvm负责加锁同步多个企图并发初始化一个类的调用 。

正是由于这里对<clinit>的隐含加锁,导致了B大帖子里死锁现象的产生。

类的初始化问题可以见《深入jvm虚拟机》 p187

通过javap -c 找不到<clinit> ,但是能看到static{}块,实际上它就是<clint> , 见R大帖子

· static  字段与 static final 字段

前者是类级别的, 后者会被搞到常量池, jvm级别的,因此访问一个类的static final 字段并不会导致该类的加载。

验证方法:

public class A{
    public static void main(String[] args){
        System.out.println(B.NAME);
        System.out.println(B.CONST_NAME);
    }
}

public class B{
    public static String NAME="bluedavy";
    public static final String CONST_NAME = "bluedavy_const";
    static{
        System.out.println("hellojava");
    }
}

javap -verbose A :

	Compiled from "A.java"
public class A extends java.lang.Object
  SourceFile: "A.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method	#7.#16;	//  java/lang/Object."<init>":()V
const #2 = Field	#17.#18;	//  java/lang/System.out:Ljava/io/PrintStream;
const #3 = Field	#19.#20;	//  B.NAME:Ljava/lang/String;
const #4 = Method	#21.#22;	//  java/io/PrintStream.println:(Ljava/lang/String;)V
const #5 = String	#23;	//  bluedavy_const
const #6 = class	#24;	//  A
const #7 = class	#25;	//  java/lang/Object
const #8 = Asciz	<init>;
const #9 = Asciz	()V;
const #10 = Asciz	Code;
const #11 = Asciz	LineNumberTable;
const #12 = Asciz	main;
const #13 = Asciz	([Ljava/lang/String;)V;
const #14 = Asciz	SourceFile;
const #15 = Asciz	A.java;
const #16 = NameAndType	#8:#9;//  "<init>":()V
const #17 = class	#26;	//  java/lang/System
const #18 = NameAndType	#27:#28;//  out:Ljava/io/PrintStream;
const #19 = class	#29;	//  B
const #20 = NameAndType	#30:#31;//  NAME:Ljava/lang/String;
const #21 = class	#32;	//  java/io/PrintStream
const #22 = NameAndType	#33:#34;//  println:(Ljava/lang/String;)V
const #23 = Asciz	bluedavy_const;
const #24 = Asciz	A;
const #25 = Asciz	java/lang/Object;
const #26 = Asciz	java/lang/System;
const #27 = Asciz	out;
const #28 = Asciz	Ljava/io/PrintStream;;
const #29 = Asciz	B;
const #30 = Asciz	NAME;
const #31 = Asciz	Ljava/lang/String;;
const #32 = Asciz	java/io/PrintStream;
const #33 = Asciz	println;
const #34 = Asciz	(Ljava/lang/String;)V;

{
public A();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:	aload_0
   1:	invokespecial	#1; //Method java/lang/Object."<init>":()V
   4:	return
  LineNumberTable: 
   line 1: 0


public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=1, Args_size=1
   0:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:	getstatic	#3; //Field B.NAME:Ljava/lang/String;
   6:	invokevirtual	#4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   9:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   12:	ldc	#5; //String bluedavy_const
   14:	invokevirtual	#4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   17:	return
  LineNumberTable: 
   line 3: 0
   line 4: 9
   line 5: 17
}

javap -verbose B:

Compiled from "B.java"
public class B extends java.lang.Object
  SourceFile: "B.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = Method	#8.#21;	//  java/lang/Object."<init>":()V
const #2 = String	#22;	//  bluedavy
const #3 = Field	#7.#23;	//  B.NAME:Ljava/lang/String;
const #4 = Field	#24.#25;	//  java/lang/System.out:Ljava/io/PrintStream;
const #5 = String	#26;	//  hellojava
const #6 = Method	#27.#28;	//  java/io/PrintStream.println:(Ljava/lang/String;)V
const #7 = class	#29;	//  B
const #8 = class	#30;	//  java/lang/Object
const #9 = Asciz	NAME;
const #10 = Asciz	Ljava/lang/String;;
const #11 = Asciz	CONST_NAME;
const #12 = Asciz	ConstantValue;
const #13 = String	#31;	//  bluedavy_const
const #14 = Asciz	<init>;
const #15 = Asciz	()V;
const #16 = Asciz	Code;
const #17 = Asciz	LineNumberTable;
const #18 = Asciz	<clinit>;
const #19 = Asciz	SourceFile;
const #20 = Asciz	B.java;
const #21 = NameAndType	#14:#15;//  "<init>":()V
const #22 = Asciz	bluedavy;
const #23 = NameAndType	#9:#10;//  NAME:Ljava/lang/String;
const #24 = class	#32;	//  java/lang/System
const #25 = NameAndType	#33:#34;//  out:Ljava/io/PrintStream;
const #26 = Asciz	hellojava;
const #27 = class	#35;	//  java/io/PrintStream
const #28 = NameAndType	#36:#37;//  println:(Ljava/lang/String;)V
const #29 = Asciz	B;
const #30 = Asciz	java/lang/Object;
const #31 = Asciz	bluedavy_const;
const #32 = Asciz	java/lang/System;
const #33 = Asciz	out;
const #34 = Asciz	Ljava/io/PrintStream;;
const #35 = Asciz	java/io/PrintStream;
const #36 = Asciz	println;
const #37 = Asciz	(Ljava/lang/String;)V;

{
public static java.lang.String NAME;

public static final java.lang.String CONST_NAME;
  Constant value: String bluedavy_const
public B();
  Code:
   Stack=1, Locals=1, Args_size=1
   0:	aload_0
   1:	invokespecial	#1; //Method java/lang/Object."<init>":()V
   4:	return
  LineNumberTable: 
   line 1: 0


static {};
  Code:
   Stack=2, Locals=0, Args_size=0
   0:	ldc	#2; //String bluedavy
   2:	putstatic	#3; //Field NAME:Ljava/lang/String;
   5:	getstatic	#4; //Field java/lang/System.out:Ljava/io/PrintStream;
   8:	ldc	#5; //String hellojava
   10:	invokevirtual	#6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   13:	return
  LineNumberTable: 
   line 2: 0
   line 5: 5
   line 6: 13


}


 

从A的常量池可以看到

  1. const #5 = String   #23;    //  bluedavy_const 
  2. const #23 = Asciz    bluedavy_const;
bluedavy_const 已经直接搞到了A的常量池里, 脱离了B ;
而对比A的代码:
3:    getstatic    #3; //Field B.NAME:Ljava/lang/String;
12:    ldc    #5; //String bluedavy_const
也可以看到, 使用两个常量的不同
另外,可以在运行代码时加上-verbose:class 打印类加载信息,如果去掉
 System.out.println(B.NAME);
仅保留
 System.out.println(B.CONST_NAME);
是不会导致B.class加载的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值