Java字节码文件常量池索引两个问题

先结合字节码文件分析一下字段是怎么在常量池中存储的:

以String类型为例:

在一个类中定义两个字段:

复制代码
public static final String a1 = "我爱北京天安门";
public static final String a2 = "我爱北京天安门";

在字节码文件中,在字段表中会出现两个字段分别为a1和a2,在a1中会存储两个索引,一个是指向变量名a1的索引,是一个字面量索引,CONSTANT_Utf8_info索引;一个是指向String对象"我爱北京天安门"的索引,是一个字符串索引,CONSTANT_String_info索引。然后点击String对象的CONSTANT_String_info索引,会指向一个字面量索引CONSTANT_Utf8_info索引,内容是"我爱北京天安门"。归根结底变量名和字符串对象都是用字面量来存储的,只不过:变量名直接指向字面量索引,字符串对象先指向字符串索引,再指向字面量索引。

那么问题来了?

  1. 为什么字符串要绕一下,为什么不直接指向字面量索引呢?

    这是因为在java中有一个字符串常量池,在运行时需要将String添加在字符串常量池中去,字符串对象先指向字符串索引,可以由此来判断改变量是不是String;如果字符串对象直接指向字面量,无法通过字面量来判断该变量是不是String 。

    一句话因为有字符串常量池!

  2. 那既然String对象需要先指向CONSTANT_String_info索引,为什么CONSTANT_String_info索引存储的是CONSTANT_Utf8_info索引,而不直接存储字符串字面量呢?

    定义以下三个字段:

    复制代码
    public static final String a1 = "abc";
    public static final String a2 = "abc";
    public static final String abc = "abc";

    这三个字段是怎么在字节码文件中存储的呢?

    字段表中有三个字段:a1、a2、abc,a1中有两个索引,变量名索引CONSTANT_Utf8_info,假设该索引值为4,直接指向"a1"字面量;String对象存储的是CONSTANT_String_info索引,该字符串索引指向字面量索引CONSTANT_Utf8_info,假设该索引值为10,该索引指向的是"abc"。a1和a2类似。假设a2的变量名索引CONSTANT_Utf8_info的值为6,其String对象存储的是CONSTANT_String_info索引,该索引指向的是CONSTANT_Utf8_info索引,值为10,与a1一致。

    对于a3,也有两个索引,变量名存储的字面量索引CONSTANT_Utf8_info的值为10,String对象存储的是字符串索引,该索引指向字面量索引,值为10。

    这样的话直接就可以进一步节省空间。可以节省变量名存储的空间。

    如果按照问题表述的,String对象需要存储一个字符串索引CONSTANT_String_info,那么CONSTANT_String_info索引直接存储字面量而不是指向一个字面量索引。在这种情况下,字符串索引存储的是字面量"abc",那么对于变量名来说,为节省空间而让变量名存储CONSTANT_String_info索引,因为这个索引里面存储的是字面量"abc"。这样的话变量名就不是一个字面量而是一个字符串对象了,显然是混乱的,是不可以的。因为字符串常量池里不仅存储字符串常量还有变量名了。

    一句话,变量名字面量与String对象字面量相同时,需要进行区分两者!

相关推荐
摇滚侠2 分钟前
DBeaver 导入数据库 导入 SQL 文件 MySQL 备份恢复
java·数据库·mysql
keep one's resolveY26 分钟前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克31 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠2 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌2 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局2 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化
阿丰资源2 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
呱牛do it2 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)
java
消失的旧时光-19433 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解
NE_STOP3 小时前
Redis--发布订阅命令和Redis事务
java