精华内容
下载资源
问答
  • java方法区和常量池

    千次阅读 2018-07-04 17:55:11
     和java堆一样,方法区也是属于线程共享的区域,存放的是java的类型信息,静态变量,运行时常量池以及jit编译后的代码等数据。  运行时常量池:  class文件中除了包含类的版本,类名,字段,方法,接口等信息,...

    方法区:

            和java堆一样,方法区也是属于线程共享的区域,存放的是java的类型信息,静态变量,运行时常量池以及jit编译后的代码等数据

            运行时常量池:

        class文件中除了包含类的版本,类名,字段,方法,接口等信息,还包含了常量池,这里面存放了编译期产生的各种 字面量以及符号引用,在类加载后进入方法区的运行时常量池中,运行时常量池相对于class常量池一个重要的特征是动态性,在运行期间也可以将新的常量放入其中,用的较多的就是String的intern方法

                           符号引用:类、接口的全限定名,字段和方法的名称以及描述符;在对java文件进行编译的过程中,并不会向C语言那样有连接这一步,也就是说class文件中不会存储方法、字段的最终内存布局信息,所以符号引用是不能被虚拟机直接使用的,虚拟机会在加载类时动态的去获取常量池中的符号引用,然后解析到对应的内存地址中,才可以使用

                         字面量:比较接近于常量的概念,如文本字符串,声明为final的常量值等。

    展开全文
  • 在上节关于数据做 == 比较时,提到了字符串常量池,经查询得知常量池既不属于堆,也不属于栈内存 ,那么常量池可能就和方法区有所关系,为此阅读《深入浅出JVM》一书,了解常量池和方法区的关联,同时对于常量池的...

    前言

    Java 的 JVM 的内存可分为 3 个区:堆内存(heap)、栈内存(stack)和方法区(method)也叫静态存储区。

    在学习的过程中经常还会听到常量池这一术语,在上节关于数据做 == 比较时,提到了字符串常量池,经查询得知常量池既不属于堆,也不属于栈内存 ,那么常量池可能就和方法区有所关系,为此阅读《深入浅出JVM》一书,了解常量池和方法区的关联,同时对于常量池的分类也有了一定的认识。

    本文所有代码都是基于 JDK1.8 进行的。

    正文

    在探讨常量池的类型之前需要明白什么是常量。用 final 修饰的成员变量表示常量,值一旦给定就无法改变!

    final 修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。

    在 Java 的内存分配中,总共 3 种常量池:

    全局字符串池(string pool也有叫做string literal pool)

    字符串常量池在 Java 内存区域的哪个位置在 JDK6.0 及之前版本,字符串常量池是放在 Perm Gen 区(也就是方法区)中,此时常量池中存储的是对象。

    在 JDK7.0 版本,字符串常量池被移到了堆中了。此时常量池存储的就是引用了。在 JDK8.0 中,永久代(方法区)被元空间取代了。

    字符串常量池是什么?

    在 HotSpot VM 里实现的 string pool 功能的是一个 StringTable 类,它是一个 Hash 表,默认值大小长度是1009;里面存的是驻留字符串的引用(而不是驻留字符串实例自身)。也就是说某些普通的字符串实例被这个 StringTable 引用之后就等同被赋予了“驻留字符串”的身份。这个 StringTable 在每个 HotSpot VM 的实例里只有一份,被所有的类共享。

    StringTable 本质上就是个 HashSet。这是个纯运行时的结构,而且是惰性(lazy)维护的。注意它只存储对java.lang.String 实例的引用,而不存储 String 对象的内容。 注意,它只存了引用,根据这个引用可以得到具体的 String 对象。

    在 JDK6.0 中,StringTable 的长度是固定的,长度就是 1009,因此如果放入 String Pool 中的 String 非常多,就会造成 hash 冲突,导致链表过长,当调用 String#intern() 时会需要到链表上一个一个找,从而导致性能大幅度下降;

    在 JDK7.0 中,StringTable 的长度可以通过参数指定:

    -XX:StringTableSize=66666

    class 文件常量池(class constant pool)

    我们都知道,class 文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 字面量比较接近 Java 语言层面常量的概念,如文本字符串、被声明为 final 的常量值等。 符号引用则属于编译原理方面的概念,包括了如下三种类型的常量:类和接口的全限定名

    字段的名称和描述符

    方法的名称和描述符

    常量池的每一项常量都是一个表,一共有如下表所示的11种各不相同的表结构数据,这每个表开始的第一位都是一个字节的标志位(取值1-12),代表当前这个常量属于哪种常量类型。

    每种不同类型的常量类型具有不同的结构,具体的结构本文就先不叙述了,本文着重区分这三个常量池的概念(读者若想深入了解每种常量类型的数据结构可以查看《深入理解java虚拟机》第六章的内容,其实是自己还没弄明白,后续回来填坑 )。

    运行时常量池(runtime constant pool)

    运行时常量池是方法区的一部分。

    当 Java 文件被编译成 class 文件之后,也就是会生成上面所说的 class 常量池,那么运行时常量池又是什么时候产生的呢?

    JVM 在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析(resolve)三个阶段。而当类加载到内存中后,JVM 就会将 class 文件常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在上面也说了,class 常量池中存的是字面量和符号引用,也就是说它们存的并不是对象的实例,而是对象的符号引用值。而经过resolve 之后,也就是把符号引用替换为直接引用,解析的过程会去查询全局字符串池,也就是上面所说的 StringTable,以保证运行时常量池所引用的字符串与全局字符串池中所引用的是一致的。

    三种常量池之间的关联

    关于 JVM 执行的时候,还涉及到了字符串常量池。

    在类加载阶段, JVM 会在堆中创建对应这些 class 文件常量池中的字符串对象实例,并在字符串常量池中驻留其引用。具体在 resolve 阶段执行。这些常量全局共享。

    这里说的比较笼统,没错,是 resolve 阶段,但是并不是大家想的那样,立即就创建对象并且在字符串常量池中驻留了引用。 JVM 规范里明确指定 resolve 阶段可以是 lazy 的。

    JVM 规范里 Class 文件常量池项的类型,有两种东西:CONSTANT_Utf8 和CONSTANT_String。前者是 UTF-8 编码的字符串类型,后者是 String 常量的类型,但它并不直接持有 String 常量的内容,而是只持有一个 index,这个 index 所指定的另一个常量池项必须是一个 CONSTANT_Utf8 类型的常量,这里才真正持有字符串的内容。

    在HotSpot VM中,运行时常量池里,

    CONSTANT_Utf8 -> Symbol*(一个指针,指向一个Symbol类型的C++对象,内容是跟Class文件同样格式的UTF-8编码的字符串)

    CONSTANT_String -> java.lang.String(一个实际的Java对象的引用,C++类型是oop)

    CONSTANT_Utf8 会在类加载的过程中就全部创建出来,而 CONSTANT_String 则是 lazy resolve 的,例如说在第一次引用该项的 ldc 指令被第一次执行到的时候才会 resolve。那么在尚未 resolve 的时候,HotSpot VM 把它的类型叫做JVM_CONSTANT_UnresolvedString,内容跟 Class 文件里一样只是一个 index;等到 resolve 过后这个项的常量类型就会变成最终的 JVM_CONSTANT_String,而内容则变成实际的那个 oop。

    看到这里想必也就明白了, 就 HotSpot VM 的实现来说,加载类的时候,那些字符串字面量会进入到当前类的运行时常量池,不会进入全局的字符串常量池(即在 StringTable 中并没有相应的引用,在堆中也没有对应的对象产生)。所以上面提到的,经过 resolve 时,会去查询全局字符串池,最后把符号引用替换为直接引用。(即字面量和符号引用虽然在类加载的时候就存入到运行时常量池,但是对于 lazy resolve 的字面量,具体操作还是会在 resolve 之后进行的。)

    关于 lazy resolution 需要在这里了解一下 ldc 指令

    简单地说,它用于将 String 型常量值从常量池中推送至栈顶。

    以下面代码为例:

    public static void main(String[] args) {

    String s = "abc";

    }

    比如说该代码文件为 Test.java,首先在文件目录下打开 Dos 窗口,执行 javac Test.java 进行编译,然后输入 javap -verbose Test 查看其编译后的 class 文件如下:

    使用 ldc 指令将"abc"加载到操作数栈顶,然后用 astore_1 把它赋值给我们定义的局部变量 s,然后 return。

    结合上文所讲,在 resolve 阶段( constant pool resolution ),字符串字面量被创建对象并在字符串常量池中驻留其引用,但是这个 resolve 是 lazy 的。换句话说并没有真正的对象,字符串常量池里自然也没有,那么 ldc 指令还怎么把值推送至栈顶并进行了赋值操作?或者换一个角度想,既然 resolve 阶段是 lazy 的,那总有一个时候它要真正的执行吧,是什么时候?

    执行 ldc 指令就是触发 lazy resolution 动作的条件

    ldc 字节码在这里的执行语义是:到当前类的运行时常量池(runtime constant pool,HotSpot VM里是ConstantPool + ConstantPoolCache)去查找该 index 对应的项,如果该项尚未 resolve 则 resolve 之,并返回 resolve 后的内容。 在遇到 String 类型常量时,resolve 的过程如果发现 StringTable 已经有了内容匹配的 java.lang.String 的引用,则直接返回这个引用;反之,如果 StringTable 里尚未有内容匹配的 String 实例的引用,则会在 Java 堆里创建一个对应内容的 String 对象,然后在 StringTable 记录下这个引用,并返回这个引用。

    可见,ldc 指令是否需要创建新的 String 实例,全看在第一次执行这一条 ldc 指令时,StringTable 是否已经记录了一个对应内容的 String 的引用。

    用以下代码做分析展示:

    public static void main(String[] args) {

    String s1 = "abc";

    String s2 = "abc";

    String s3 = "xxx";

    }

    查看其编译后的 class 文件如下:

    用图解的方式展示:

    String s1 = "abc";resolve 过程在字符串常量池中发现没有”abc“的引用,便在堆中新建一个”abc“的对象,并将该对象的引用存入到字符串常量池中,然后把这个引用返回给 s1。

    String s2 = "abc"; resolve 过程会发现 StringTable 中已经有了”abc“对象的引用,则直接返回该引用给 s2,并不会创建任何对象。

    String s3 = "xxx"; 同第一行代码一样,在堆中创建对象,并将该对象的引用存入到 StringTable,最后返回引用给 s3。

    常量池与 intern 方法

    public static void main(String[] args) {

    String s1 = "ab";//#1

    String s2 = new String(s1+"d");//#2

    s2.intern();//#3

    String s4 = "xxx";//#4

    String s3 = "abd";//#5

    System.out.println(s2 == s3);//true

    }

    查看其编译后的 class 文件如下:

    通过 class 文件信息可知,“ab”、“d”、“xxx”,“abd”进入到了 class 文件常量池,由于类在 resolve 阶段是 lazy 的,所以是不会创建实例对象,更不会驻留字符串常量池。

    图解如下:

    进入 main 方法,对每行代码进行解读。1,ldc 指令会把“ab”加载到栈顶,换句话说,在堆中创建“ab”对象,并把该对象的引用保存到字符串常量池中。

    2,ldc 指令会把“d”加载到栈顶,然后有个拼接操作,内部是创建了一个 StringBuilder 对象,一路 append,最后调用 StringBuilder 对象的 toString 方法得到一个 String 对象(内容是 abd,注意 toString 方法会 new 一个 String 对象),并把它赋值给 s2(赋值给 s2 的依然是对象的引用而已)。注意此时没有把“abd”对象的引用放入字符串常量池。

    3,intern 方法首先会去字符串常量池中查找是否有“abd”对象的引用,如果没有,则把堆中“abd”对象的引用保存到字符串常量池中,并返回该引用,但是我们并没有使用变量去接收它。

    4,无意义,只是为了说明 class 文件中的“abd”字面量是#5时得到的。

    5,字符串常量池中已经有“abd”对象的引用,因此直接将该引用返回给 s3。

    总结

    1、全局字符串常量池在每个 VM 中只有一份,存放的是字符串常量的引用值。

    2、class 常量池是在编译的时候每个 class 都有的,在编译阶段,存放各种字面量和符号引用。

    3、运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个 class 都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。

    4、class 文件常量池中的字符串字面量在类加载时进入到运行时常量池,在真正在 resolve 阶段(即执行 ldc 指令时)时将该字符串的引用存入到字符串常量池中,另外运行时常量池相对于 class 文件常量池具备动态性,有些常量不一定在编译期产生,也就是并非预置入 class 文件常量池的内容才能进入到方法区运行时常量池,运行期间通过 intern 方法,将字符串常量存入到字符串常量池中和运行时常量池(关于优先进入到哪个常量池,私以为先进入到字符串常量池,具体实现还望大神指教)。

    参考链接

    展开全文
  • 最近一直被方法区里面存着什么东西困扰着?...更加详细一点的说法是方法区里存放着类的版本,字段,方法,接口和常量池。常量池里存储着字面量和符号引用。符号引用包括:1.类的全限定名,2.字段名和属...

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

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

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

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

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

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

    bf33b18bb90ec101943fff97f9b7fcf8.png

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

    b57f5fc12df1da936f14809bf3daf226.png

    可以看到在方法区里的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

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

    170a002419c7113fbd128d250787b748.png

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

    下面是原java代码

    public class TestInt {

    private String str = "hello";

    void printInt(){

    System.out.println(65535);

    }

    }

    经过反编译后获得class文件是下面这样的  javap -v -verbose xxx.class

    1a4055270788b220c534c16d015d8b40.png

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

    静态常量池和动态常量池的关系以及区别

    静态常量池存储的是当class文件被java虚拟机加载进来后存放在方法区的一些字面量和符号引用,字面量包括字符串,基本类型的常量,符号引用其实引用的就是常量池里面的字符串,但符号引用不是直接存储字符串,而是存储字符串在常量池里的索引。

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

    总结:

    方法区里存储着class文件的信息和动态常量池,class文件的信息包括类信息和静态常量池。可以将类的信息是对class文件内容的一个框架,里面具体的内容通过常量池来存储。

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

    下面有一篇文章写的是比较好的

    http://blog.csdn.net/vegetable_bird_001/article/details/51278339

    https://www.cnblogs.com/holos/p/6603379.html

    展开全文
  • Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。1)所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分...

    1、什么是常量

    用final修饰的成员变量表示常量,值一旦给定就无法改变!

    final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。

    Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。

    1)所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。

    2)

    而运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

    2、class字节码文件​

    ​class文件的@头4个字节称为魔数@,它的唯一作用就是确定这个文件时候是一个能被虚拟机接受的class文件。很多图片格式都用一个魔数来标识文件类型,比如png和jpg等。在java的class文件中,这个数是0xcafebabe。接下来就是class文件的版本号,第5、6个字节是@次版本号@,第7、8个字节是@主版本号@。在这里,次版本号是0,主版本号是52,(十六进制是34),紧接着主版本号的就是@常量池@,常量池可以理解为class文件的资源仓库,它是class文件结构中与其它项目关联最多的数据类型,也是占用class文件空间最大的数据项目之一,也是class文件中第一个出现的表类型数据项目。这些符号引用在虚拟机中如果不经过转换则无法与实际内存相连接,即无法被虚拟机直接使用,在虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析并翻译到具体的内存地址中。每项常量都是一个表,而由于各个常量的类型不一,大小也不相同,所以同样需要一个u1类型的数据来标记常量的类型,以确定其后的常量表的格式。

    常量池(constant_pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量和符号引用。

    常量池主要用于存放两大类常量:字面量(Literal)和符号引用量(Symbolic

    References),字面量相当于Java语言层面常量的概念,如文本字符串,声明为final的常量值等,符号引用则属于编译原理方面的概念,包括了如下三种类型的常量:

    类和接口的全限定名;字段名称和描述符;方法名称和描述符

    则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值在-128到127时才可使用对象池。

    ​在常量池之后,紧接着的2个字节代表@访问标志@,即在前面说到的,这个Class是类还是接口,是用哪个修饰符来修饰,abstract,public等,还有,如果是类的话,是否被声明为final,等等。

    访问标志之后,则是@类索引、父索引与接口索引@的集合。类索引和父类索引都是一个u2类型的数据,而接口索引集合是一组u2类型的数据的集合,Class文件中由这三项数据来确定这个类的继承关系。类索引用来确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名,接口索引集合用来描述这个类实现了哪些接口,这些被实现的接口将按实现或继承的顺序从左到右的顺序排列在接口的索引集合中。类索引、父类索引和接口索引都按顺序排列在访问标志之后。

    接下来就是@字段表@了,此处字段表存的就是前文说的类成员变量或实例成员变量,但不包括方法内部声明的变量。如果类存在父类,则除非子类覆盖了父类的字段定义,否则在子类中不会列出从超类或父接口中继承而来的字段,但有可能列出原来java代码中不存在的字段,譬如在内部类为了保持对外部类的访问性,会自动添加指向外部类实例的字段。另外,java中是不允许出现相同的字段名的,但对于字节码来说,如果两个字段的描述符不一致,则字段重名是合法的。

    字段表之后就是@方法表@集了。方法表集合与字段表集合的结构形式几乎完全一致。此处,方法中的代码的存放位置则是方法表的属性表中的一项名为"Code"的属性里面。与字段表集合相对应的,如果父类方法在子类中没有被重写(Override),则方法表集合中就不会出现来自父类的方法信息。

    ​3、方法区中的运行时常量池

    运行时常量池是方法区的一部分。CLass文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。

    运行时常量池相对于CLass文件常量池的另外一个重要特征是具备动态性,方法。

    4、常量池的好处

    常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。

    (1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。

    (2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等

    String s1=new String("abc"); 为例

    首先你要理解constant   pool,

    这是一个特殊的共享区域,literate,

    Class这些可以在内存中共享的不经常改变的东西,都可以放在这里。

    如果你用了String   s1

    =   new

    String("abc");

    那么,会有两个String被创建,一个是你的Class被CLassLoader加载时,你的"abc"被作为常量读入,在constant

    pool里创建了一个共享的"abc"

    然后,当调用到new

    String("abc")的时候,会在heap里创建这个new

    String("abc");

    考虑类加载阶段和实际执行时。

    (1)类加载对一个类只会进行一次。"abc"在类加载时就已经创建并驻留了(如果该类被加载之前已经有"abc"字符串被驻留过则不需要重复创建用于驻留的"xyz"实例)。驻留的字符串是放在全局共享的字符串常量池中的。

    (2)在这段代码后续被运行的时候,"abc"字面量对应的String实例已经固定了,不会再被重复创建。所以这段代码将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s1

    持有。

    这条语句创建了2个对象。

    展开全文
  • 1. 方法区:存放全局变量静态变量2.常量池:存放常量字符串3.栈:存放函数的参数值,局部变量的值4.堆:存放成员变量(实例变量),一般内存泄漏会发生堆:存放所有new 出来的对象栈:存放基本类型的变量数据对象...
  • 版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接本声明。本文链接:https://blog.csdn.net/qq_34490018/article/details/82110578目录JVM相关知识String源码分析Srtring在JVM...
  • 运行时常量池方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String...
  • 运行时常量池方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String...
  • 在上节关于数据做 == 比较时,提到了字符串常量池,经查询得知常量池既不属于堆,也不属于栈内存 ,那么常量池可能就和方法区有所关系,为此阅读《深入浅出JVM》一书,了解常量池和方法区的关联,同时对于常量池的...
  • 在上节关于数据做 == 比较时,提到了字符串常量池,经查询得知常量池既不属于堆,也不属于栈内存 ,那么常量池可能就和方法区有所关系,为此阅读《深入浅出JVM》一书,了解常量池和方法区的关联,同时对于常量池的...
  • 栈(stack):主要保存基本类型(或者叫内置类型)(char、...堆(heap):用于存储对象数组常量池常量池的划分Class 文件常量池运行时常量池字符串常量池1. Class 文件常量池Class 文件常量池指的是编译生成的 class ...
  • 小菜先拙劣的表达一下jvm虚拟内存分布: 程序计数器是jvm执行程序的流水线,存放一些跳转... 方法区存放了一些常量、静态变量、类信息等,可以理解成class文件在内存中的存放位置。 虚拟机堆是jvm执行jav...
  • 运行时常量池方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String...
  • 运行时常量池方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String...
  • 方法区和常量池

    2018-09-12 09:40:05
    方法区和常量池 2017年11月15日 21:20:11 阅读数:7262更多 个人分类: Java虚拟机 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangbiao007/article/details/78545189  ...
  • 本文用最简洁的描述,来总结出Java内存区域和常量池的相关知识,如需更加深入学习Java内存区域以及常量池,可参考阅读《深入Java虚拟机》或者网上优秀博文。运行时数据区运行数据区包含以下几个区域:方法区(Method ...
  • java8内存结构图虚拟机内存与本地内存的区别Java虚拟机在执行的时候会把管理的内存分配成不同的区域,这些区域被称为虚拟机内存,同时,对于虚拟机没有直接管理的物理内存,也有一定的利用,这些被利用却不在虚拟机...
  • 要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机。(Sun JDK 和 Open JDK除了注释不同,代码实现基本上是一样的) 以下说的内容都是围绕HotSpot。 Stack(栈)...
  • 栈(stack):主要保存基本类型(或者叫内置类型)(char、...堆(heap):用于存储对象数组常量池常量池的划分Class 文件常量池运行时常量池字符串常量池1. Class 文件常量池Class 文件常量池指的是编译生成的 class ...
  • 标签:运行时常量池方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此...
  • 运行时常量池方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。String.intern()是一个native方法,它的作用是:如果字符串常量池中已经包含了一个等于此String...
  • 1:栈在函数中定义的一些基本类型的变量数据对象的引用...每个线程包含一个栈,每个栈中的数据(原始类型对象引用)都是私有的,其他栈不能访问。栈分为3个部分:基本类型变量、执行环境上下文、操作指令(存...
  • 栈存放基本类型的变量数据对象的引用(就是一个名字),对象本身不存放在栈中,而是存放在堆或者常量池中。栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解...
  • 常量池:String.intern()是一个Native方法,他的作用是如果常量池中已经包含一个等于String对象的字符串,则返回代表池中这个字符串String对象,否则将此字符串放...方法区方法区存放Class相关信息 直接内存: ...
  • java虚拟机运行时常量池时间:20180228运行时常量池方法区的一部分。Class文件(也就是.java文件编译后生成的字节码.class文件)中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant ...
  • 分析一下问题:java虚拟机运行时数据区的内存模型有这几部分:方法区、堆、java栈、pc寄存器、本地方法栈(常量池并不属于jvm的模型范畴),我不清楚汇编语言中是怎么解释这一切是怎么回事,那么...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,186
精华内容 874
关键字:

java方法区和常量池

java 订阅