方法区里面有什么——class文件、class文件常量池、运行时常量池

最近一直被方法区里面存着什么东西困扰着?

       1.方法区里存class文件信息和class文件常量池是个什么关系。

        2.class文件常量池和运行时常量池是什么关系。        

        方法区存着类的信息,常量和静态变量,即类被编译后的数据。这个说法其实是没问题的,只是太笼统了。更加详细一点的说法是方法区里存放着类的版本,字段,方法,接口和常量池。常量池里存储着字面量和符号引用。

       符号引用包括:1.类的全限定名,2.字段名和属性,3.方法名和属性。

       下面一张图是我画的方法区,class文件信息,class文件常量池和运行时常量池的关系

       

       下面一张图用来表示方法区class文件信息包括哪些内容:

       

         可以看到在方法区里的class文件信息包括:魔数,版本号,常量池,类,父类和接口数组,字段,方法等信息,其实类里面又包括字段和方法的信息。

         下面的图表是class文件中存储的数据类型             

类型 名称 数量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attribute_count 1
attribute_info attributes attributes_count

       下面用一张图来表示常量池里存储的内容:

        这里写图片描述

用一个class文件实际反编译一下

下面是原java代码

[java] view plain copy

  1. public class TestInt {    
  2.     private String str = "hello";    
  3.     void printInt(){    
  4.         System.out.println(65535);    
  5.     }    
  6. }   


经过反编译后获得class文件是下面这样的

可以看出被反编译的class文件中的内容和上面所说的是能对应上的。这就解答了class文件和class文件常量池的关系

class文件常量池和运行时常量池的关系以及区别

class文件常量池存储的是当class文件被java虚拟机加载进来后存放在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量。

运行时常量池是当class文件被加载完成后,java虚拟机会将class文件常量池里的内容转移到运行时常量池里,在class文件常量池的符号引用有一部分是会被转变为直接引用的,比如说类的静态方法或私有方法,实例构造方法,父类方法,这是因为这些方法不能被重写其他版本,所以能在加载的时候就可以将符号引用转变为直接引用,而其他的一些方法是在这个方法被第一次调用的时候才会将符号引用转变为直接引用的。

总结:

方法区里存储着class文件的信息和运行时常量池,class文件的信息包括类信息和class文件常量池。

运行时常量池里的内容除了是class文件常量池里的内容外,还将class文件常量池里的符号引用转变为直接引用,而且运行时常量池里的内容是能动态添加的。例如调用String的intern方法就能将string的值添加到String常量池中,这里String常量池是包含在运行时常量池里的,但在jdk1.8后,将String常量池放到了堆中。

你可能感兴趣的:(linq,c#)