关于成员变量的处理【转】

http://bonnie0203.i170.com/user/yqj2065/Article_113694
 
 
从JVM角度看命名常量final、类变量static和static final以及一般实例变量的处理。访问修饰符暂时全部为private。

一、命名常量(final以及static final):

 

要点:

*类变量(static variables):Memory for class (static) variables declared in the class is also taken from the method area.(information about loaded types is stored in a logical area of memory called the method area.)

Class variables are shared among all instances of a class and can be accessed even in the absence of any instance. These variables are associated with the class--not with instances of the class--so they are logically part of the class data in the method area. Before a Java Virtual Machine uses a class, it must allocate memory from the method area for each non-final class variable declared in the class.

* 命名常量(final以及static final):Constants (class variables declared final) are not treated in the same way as non-final class variables.

Every type that uses a final class variable gets a copy of the constant value in its own constant pool. As part of the constant pool, final class variables are stored in the method area--just like non-final class variables. But whereas non-final class variables are stored as part of the data for the type that declares them, final class variables are stored as part of the data for any type that uses them. This special treatment of constants is explained in more detail in Chapter 6, "The Java Class File."

 

1、final成员变量。

public class Yqj{
    private final int aFinalInt = 678;
    private final int sssss = 321;
    private final String SourceFile = "SourceFile";
    private final AAA ref = new AAA();
}
每个域的一般信息由cp_info 中CONSTANT_Fieldref (9)结构描述,分别为CONSTANT_Class 和CONSTANT_NameAndType :

#2 CONSTANT_Fieldref_info 描述#9,#30为Yqj ,aFinalInt.

#3 CONSTANT_Fieldref_info 描述#9,#31为Yqj ,sssss.

#5 CONSTANT_Fieldref_info 描述#9,#33为Yqj ,SourceFileLjava/lang/String;

#8 CONSTANT_Fieldref_info 描述#9,#35为Yqj ,refLAAA;

 

每个域有一个field_info 结构描述其修饰符、名称、描述和属性,如aFinalInt成员变量的field_info结构为:

access_flags : private final (修饰符)

name_index : 指向cp_info#11,CONSTANT_Utf8表示的aFinalInt。(成员变量的名称字符表示)

descriptor_index:指向cp_info#12,CONSTANT_Utf8表示的I。(成员变量的类型字符表示)即int

包含一个attribute_info :

     attribute_name_index 指向cp_info#13,即ConstantValue

     attribute_length:ConstantValue_attribute structure 必须为2

   constantvalue_index  :指向cp_info#14,CONSTANT_Integer_info 表示的678

其他域有类似的结构,

sssss成员变量的field_info结构中所包含一个attribute_info中,constantvalue_index 指向cp_info#16,即321.

SourceFile的name_index ,其实总是存在的,它是JVM中预定义的字符串(java/lang/String、<init>、()V、I、SourceFile等等)之一,所以也就指向cp_info#17。而且其constantvalue_index 指向cp_info#4,一个CONSTANT_String_info 结构(而不是CONSTANT_Utf8)而后者指向cp_info#17。

(按照Java语言中的说法,应该是不在运行时常量池中单独为字符串常量"SourceFile"的创建一个对象。)

对于成员变量ref,name_index指向cp_info#19即CONSTANT_Utf8表示的ref,类型为"LAAA; ",注意它没有属性。

0 0 
12 18 //private final
0 0 
13 19 // #19即CONSTANT_Utf8表示的ref
0 0 
14 20 //LAAA;
0 0 
0 0    //attributes_count = 0
0 0 
1 1   //methods_count = 1,say<init>
**如果有成员变量private final Boolean b = Boolean.TRUE;

cp_info 中多出了一个CONSTANT_Fieldref_info ,它们在常量池表中以2个CONSTANT_Utf8表示TRUE和java/lang/Boolean,没有ConstantValue属性。(这没有特殊性。)

 

2、类变量static

public class Yqj{
    private static int aFinalInt = 678;
    private static int sssss = 321;
    private static String str = "SourceFile";
    private static AAA ref = new AAA();
}
每个域的由cp_info的CONSTANT_Fieldref (9)结构依旧。

每个域有一个field_info 结构描述其修饰符、名称、描述和属性,此时都没有ConstantValue属性;修饰符为private static。

常量池表中有CONSTANT_String_info 结构,其指向一个CONSTANT_Utf8;

678等等当然没有CONSTANT_Integer_info 表示它们了,它们是文字。

有一个<clinit>方法将完成static变量的初始化。

 

3、static final

命名常量常常同时用public static final修饰。

基本变量和String变量有ConstantValue属性,有对应的CONSTANT_Integer_info 、CONSTANT_String_info 结构;其他类类型变量如ref没有ConstantValue属性,通过<clinit>方法将完成static变量ref的初始化。

 

4、一般实例变量

源代码中的字符串文字如"abc"总有一个CONSTANT_String_info 结构加以表示,指向一个CONSTANT_Utf8结构。但是所有的域都没有ConstantValue属性。有一个<init>方法将完成一般实例变量的初始化。

 

5、String问题

public class Yqj{
    private  int aFinalInt = 678;   
    private  String str = "SourceFile";
    private  AAA ref = new AAA();
    void foo(){
        int sssss = 321;
        String st ="abc";
        String str ="a"+"bc";
    }
}
 “abc”和"a"+"bc"保存的是同一个常量池表项#8为CONSTANT_String_info 结构,后者指向一个CONSTANT_Utf8结构。按照Java语言的解释就是: “abc”和"a"+"bc"这两个String文字(理解成命名常量倒是不错,持有)指向同一个String对象的引用。(然而String对象不是CONSTANT_Utf8结构,该结构是一个char[]).foo方法中,

 0 sipush 321
 3 istore_1
 4 ldc #8 <abc>  //#8是当前类常量池表中的一个索引,对应的常量池项是CONSTANT_String。The runtime

      //constant pool  entry is a symbolic  reference to a string literal 
 6 astore_2 //the runtime constant pool entry must be a reference to an instance of class String representing a

         // string literal . A reference     to that instance, value, is pushed onto the operand stack.
 7 ldc #8 <abc>
 9 astore_3
10 return


多个类文件,多线程时,class文件格式的(静态)分析就到头了。

 

 

6、关于final形参 

public class Yqj{
    void foo(final int i,int j){
        class InB{
            public void foo(){System.out.print(i);}
        }
    }
}

方法foo的参数i 有final和没有final两者的Yqj.class是一样的;但是只有final修饰局部变量时它才能够在内部类中使用,如果使用了i ,它将被作为Yqj$1InB的成员变量;j以final修饰但不在内部类中使用仍然被编译器忽略其final。

 

你可能感兴趣的:(jvm,多线程,J#,Access)