JVM中Class文件常量池中存放了哪些信息

目录

直接引用和符号引用简述:

Class常量池

局部变量的讨论

拓展知识


直接引用和符号引用简述:

举个例子:现在我要在A类中引用到B类,符号引用就是我只要知道B类的全类名是什么就可以了,而不用知道B类在内存中的那个具体位置(有可能B类还没有被加载进内存呢)。直接引用就相当于是一个指针,能够直接或者间接的定位到内存中的B类的具体位置。将符号引用转换为直接引用简单来说就是:在A类中可以通过使用B类的全类名转换得到B类在内存中的具体位置。

Class常量池

常量池中主要存放两类数据,一是字面量、二是符号引用。

字面量:比如String类型的字符串值或者定义为final类型的常量的值。

符号引用:

  1. 类或接口的全限定名(包括他的父类和所实现的接口)
  2. 变量或方法的名称
  3. 变量或方法的描述信息
  4. this
  •     方法的描述:参数个数、参数类型、方法返回类型等等
  •     变量的描述信息:变量的返回值

局部变量的讨论

tip:网上有文章说不会将局部变量的变量名放入到常量池中?关于是否会将局部变量放入到常量池中,测试结果如下:

        ①.当在一个方法中有给局部变量赋值的语句时,会将局部变量名放入到常量池

        ②.当在方法中只是声明了一个局部变量,并没有为该局部变量的赋值操作时,不会将该局部变量名放入到常量池中

代码示例:

用下面这个简单的类来测试上面的结论:

public class MyDemo extends Demo implements IDemo {

    private int a;

    public void method(){
        int b = 0;
    }
}

情况一:从上面的代码中可以看到我们声明了一个全局变量a,一个局部变量b,并且为局部变量b做了赋初值操作。使用javac将该类编译成字节码文件,得到MyDemo.class,使用javap -verbose MyDemo反编译字节码文件如下:

情况二:

我们将方法中的b = 0;不进行赋值操作,然后重新编译源代码,仍然使用Javap进行反编译,结果如下,发现常量池中并没有变量b。

说明:一个类的class文件中并不会将他所继承的父类中的即使是Final类型的常量数据放入到常量池中,也不会将他所实现的接口中的常量放到常量池中。如果在该类中使用到了另一个类的编译期常量那么在编译时也会将该常量放入到常量池中。

拓展知识

来自:https://www.jianshu.com/p/cf78e68e3a99

运行时常量池是方法区的一部分,所以也是全局共享的。我们知道,jvm在执行某个类的时候,必须经过加载、连接(验证,准备,解析)、初始化,在第一步的加载阶段,虚拟机需要完成下面3件事情:

  • 通过一个类的“全限定名”来获取此类的二进制字节流
  • 将这个字节流所代表的静态储存结构转化为方法区的运行时数据结构
  • 在内存中生成一个类代表这类的java.lang.Class对象,作为方法区这个类的各种数据访问的入口

  这里需要说明的一点是,类对象和普通的实例对象是不同的,类对象是在类加载的时候生成的,普通的实例对象一般是在调用new之后创建。

  上面第二条,将class字节流代表的静态储存结构转化为方法区的运行时数据结构,其中就包含了class文件常量池进入运行时常量池的过程。这里需要强调一下,不同的类共用一个运行时常量池,同时在进入运行时常量池的过程中,多个class文件中常量池中相同的字符串只会存在一份在运行时常量池中,这也是一种优化。

  运行时常量池的作用是存储 Java class文件常量池中的符号信息。运行时常量池 中保存着一些 class 文件中描述的符号引用,同时在类加载的“解析阶段”还会将这些符号引用所翻译出来的直接引用(直接指向实例对象的指针)存储在 运行时常量池 中。

  运行时常量池相对于 class 常量池一大特征就是其具有动态性,Java 规范并不要求常量只能在运行时才产生,也就是说运行时常量池中的内容并不全部来自 class 常量池,class 常量池并非运行时常量池的唯一数据输入口;在运行时可以通过代码生成常量并将其放入运行时常量池中,这种特性被用的较多的是String.intern()。

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值