static final修饰的基础变量(加String类型)的奇

2020-04-27  本文已影响0人  睦月MTK

声明:我在此只是陈述我看到的现象,并根据该现象去推断发生的理由,所以有些结论只是个人猜测,错误之处请指正


一、问题代码及实验结果
public class TestClassOne {
    public static final String finalFieldString = "final field String";
    public static final Integer finalFieldInteger = 20;
    public static final int finalFieldInt = 20;
}

名称未大写,注意

public class Main {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        TestClassOne to = new TestClassOne();
        Field uf = Unsafe.class.getDeclaredField("theUnsafe");
        uf.setAccessible(true);
        Unsafe U = (Unsafe) uf.get(null);

        Field toFinalFieldString = to.getClass().getDeclaredField("finalFieldString");
        U.putObjectVolatile(U.staticFieldBase(toFinalFieldString) , U.staticFieldOffset(toFinalFieldString) , "final field String modified");
        System.out.println(toFinalFieldString.get(null));
        System.out.println(TestClassOne.finalFieldString);

        System.out.println("***************************分隔线*****************");

        Field toFinalFieldInteger = to.getClass().getDeclaredField("finalFieldInteger");
        U.putObjectVolatile(U.staticFieldBase(toFinalFieldInteger) , U.staticFieldOffset(toFinalFieldInteger) , Integer.valueOf(22));
        System.out.println(toFinalFieldInteger.get(null));
        System.out.println(TestClassOne.finalFieldInteger);

        System.out.println("***************************分隔线*****************");

        Field toFinalFieldInt = to.getClass().getDeclaredField("finalFieldInt");
        U.putIntVolatile(U.staticFieldBase(toFinalFieldInt) , U.staticFieldOffset(toFinalFieldInt) , 22);
        System.out.println(toFinalFieldInt.get(null));
        System.out.println(TestClassOne.finalFieldInt);
    }

}
final field String modified
final field String
***************************分隔线*****************
22
22
***************************分隔线*****************
22
20
Classfile 隐藏/TestClassOne.class
  Last modified 2020-4-27; size 606 bytes
  MD5 checksum 23375c3bbaa1a10b0d97d201a6ac77f3
  Compiled from "TestClassOne.java"
public class cn.mtk.ust.TestClassOne
  minor version: 0
  major version: 55
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #5.#25         // java/lang/Object."<init>":()V
   #2 = Methodref          #26.#27        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #3 = Fieldref           #4.#28         // cn/mtk/ust/TestClassOne.finalFieldInteger:Ljava/lang/Integer;
   #4 = Class              #29            // cn/mtk/ust/TestClassOne
   #5 = Class              #30            // java/lang/Object
   #6 = Utf8               finalFieldString
   #7 = Utf8               Ljava/lang/String;
   #8 = Utf8               ConstantValue
   #9 = String             #31            // final field String
  #10 = Utf8               finalFieldInteger
  #11 = Utf8               Ljava/lang/Integer;
  #12 = Utf8               finalFieldInt
  #13 = Utf8               I
  #14 = Integer            20
  #15 = Utf8               <init>
  #16 = Utf8               ()V
  #17 = Utf8               Code
  #18 = Utf8               LineNumberTable
  #19 = Utf8               LocalVariableTable
  #20 = Utf8               this
  #21 = Utf8               Lcn/mtk/ust/TestClassOne;
  #22 = Utf8               <clinit>
  #23 = Utf8               SourceFile
  #24 = Utf8               TestClassOne.java
  #25 = NameAndType        #15:#16        // "<init>":()V
  #26 = Class              #32            // java/lang/Integer
  #27 = NameAndType        #33:#34        // valueOf:(I)Ljava/lang/Integer;
  #28 = NameAndType        #10:#11        // finalFieldInteger:Ljava/lang/Integer;
  #29 = Utf8               cn/mtk/ust/TestClassOne
  #30 = Utf8               java/lang/Object
  #31 = Utf8               final field String
  #32 = Utf8               java/lang/Integer
  #33 = Utf8               valueOf
  #34 = Utf8               (I)Ljava/lang/Integer;
{
  public static final java.lang.String finalFieldString;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: String final field String

  public static final java.lang.Integer finalFieldInteger;
    descriptor: Ljava/lang/Integer;
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

  public static final int finalFieldInt;
    descriptor: I
    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
    ConstantValue: int 20

  public cn.mtk.ust.TestClassOne();
    //...构造方法描述略

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: bipush        20
         2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
         5: putstatic     #3                  // Field finalFieldInteger:Ljava/lang/Integer;
         8: return
      LineNumberTable:
        line 7: 0
}
SourceFile: "TestClassOne.java"
Classfile 隐藏/Main.class
  Last modified 2020-4-27; size 2011 bytes
  MD5 checksum 4af93f788bfb219460e95b2975aede4a
  Compiled from "Main.java"
public class cn.mtk.ust.Main
  minor version: 0
  major version: 55
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   //...常量池略
{
  public cn.mtk.ust.Main();
     //...Main方法描述略

  public static void main(java.lang.String[]) throws java.lang.NoSuchFieldException, java.lang.IllegalAccessException;
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=5, locals=7, args_size=1
        //...略
        71: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        74: ldc           #17                 // String final field String
        76: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        79: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
        82: ldc           #19                 // String ***************************分隔线*****************
        84: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        //...略
       131: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
       134: getstatic     #22                 // Field cn/mtk/ust/TestClassOne.finalFieldInteger:Ljava/lang/Integer;
       137: invokevirtual #16                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
       140: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
       143: ldc           #19                 // String ***************************分隔线*****************
       145: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        //...略
       189: getstatic     #15                 // Field java/lang/System.out:Ljava/io/PrintStream;
       192: bipush        20
       194: invokevirtual #25                 // Method java/io/PrintStream.println:(I)V
       197: return
      LineNumberTable:
        //...略
      LocalVariableTable:
        //...本地变量表略
    Exceptions:
      throws java.lang.NoSuchFieldException, java.lang.IllegalAccessException
}
SourceFile: "Main.java"

二、问题分析及推论

参考文档:

上一篇 下一篇

猜你喜欢

热点阅读