`
lilisalo
  • 浏览: 1109986 次
文章分类
社区版块
存档分类
最新评论

JAVA:对常量池的编译时解析

 
阅读更多

from Inside the JAVA2 Virtual Machine P 294- 296


在java文件中,指向编译时常量的类的static final 变量, 会被在运行时解析为一个局部的常量值(也就是说编译成字节码时,会把那些在编译时就能确定的static final 变量直接用常量代替)。这对所有的primitive types(就像int ,float等)和java.lang.String都适用。


这些特别的常量机制源自于java语言的两个特点。第一,常量的局部复制 让static final 变量能够被应用到 switch case语句中。tableswitch 和 lookupswitch 是字节码中实现switch逻辑的指令,它们需要在字节码中查找到case值。而这些指令是不支持运行时对变量的解析的。

另外一个动机是对if等判断语句的编译优化Java支持根据解析判定值为一个编译时常量来简化对判断语句的编译。如下代码:

因为编译器会对primitive 常量进行特殊处理,进儿对if判断语句进行优化,决定是否包含某段代码。

main方法的字节码如下:

这里根本没有出现对AntHill类的调用,也就不会链接、初始化AntHill类。

编译器直接在编译时优化了代码,将AntHill.debug转化为对局部常量的访问,并进一步简化了if判断语句。

如果在源代码如下:


main方法字节码为:

没有任何其他代码。

同时,我们需要注意,重新编译的时候不能仅仅编译AntHill.class ,而是要编译所有文件!

(笔者感悟:看来要谨慎使用final static 的 primitive 变量!!)





分享到:
评论

相关推荐

    JD-GUI,JDGUI,java反编译工具

    java反编译工具: JD-GUI JD-GUI 是一个用 C++ 开发的 Java 反编译工具... (它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。)

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    8.1.3 常量池解析 8.1.4 解析constant_class_info入口 8.1.5 解析constant_fieldref_info入口 s.1.6 解析constant_methodref_info入口 8.1.7 解析constant_interface-methodref_info入口 8.1.8 ...

    Java思维导图

    Java代码在进行Javac编译的时候,并不像C和C++那样有“连接”这一步骤,而是在虚拟机加载Class文件的时候...当虚拟机运行时,需要从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址之中。

    深入Java虚拟机

    8.1.3 常量池解析 8.1.4 解析CONSTANT_Class_info入口 8.1.5 解析CONSTANT_Fieldref_info 入口 S.1.6 解析CONSTANT_Methodref_info 入口 8.1.7 解析CONSTANT_Interface- Methodref_info入口 ...

    详解JAVA类加载机制(推荐)

    字节码文件格式主要分为两部分:常量池和方法字节码。 二、类加载 类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。过程共有七个阶段,其中到初始化之前的都是属于类加载的部分 加载—-验证—-准备—-...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    Java内存区域与内存溢出异常 / 24 2.1 概述 / 24 2.2 运行时数据区域 / 25 2.2.1 程序计数器 / 25 2.2.2 Java虚拟机栈 / 26 2.2.3 本地方法栈 / 27 2.2.4 Java堆 / 27 2.2.5 方法区 / 28 2.2.6 运行时常量池 ...

    深入java虚拟机第二版

    8.1.3 常量池解析 8.1.4 解析CONSTANT_Class_info入口 8.1.5 解析CONSTANT_Fieldref_info 入口 S.1.6 解析CONSTANT_Methodref_info 入口 8.1.7 解析CONSTANT_Interface- Methodref_info入口 8.1.8 解析...

    Java虚拟机

    2.4.3 方法区和运行时常量池溢出 2.4.4 本机直接内存溢出 2.5 本章小结 第3章 垃圾收集器与内存分配策略 3.1 概述 3.2 对象已死吗 3.2.1 引用计数算法 3.2.2 可达性分析算法 3.2.3 再谈引用 3.2.4 生存...

    深入JAVA虚拟机(第2版)

    8.1.3 常量池解析 8.1.4 解析CONSTANT_Class_info入口 8.1.5 解析CONSTANT_Fieldref_info入口 S.1.6 解析CONSTANT_Methodref_info入口 8.1.7 解析CONSTANT_Interface-Methodref_info入口 8.1.8 ...

    2Java SE(上).doc

    使用new关键字创建的字符串对象由于不会存入常量池也不会检查常量池,所以不会重用对象。 java编译器有一个优化措施,就是若计算表达式运算符两边都是字面量,那么编译器在生成class文件时就将结果计算完毕并保存...

    Java 虚拟机面试题全面解析(干货)

    运行时常量池( Runtime Constant pool)是方法区的一部分。保存 Class文件中的符号引 用、翻译岀来的直接引用。运行时常量池可以在运行期间将新的常量放入池中 Java中对象访问是如何进行的? Object ob j new Object...

    java面试题

    答:运行时异常时(JVM)java虚拟机在运行过程中发生的问题,比如:内存溢出等问题。这类异常没法要求程序员去一一捕获并抛出,一般异常是Java类库或程序员自己写的代码发生的错误,这类异常可以由我们去一一捕获并...

    Ming:Class文件解析器

    MingClass文件解析器关于对Java编译后的Class文件进行解析版本(更新说明)0.1.0修复读取Double和Long类型时出现找不到指定类型的错误移除jdk9的方法InputStream#readAllBytes(),替换为Files#readAllBytes(),以支持...

    java 面试题 总结

    java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 6、说出Servlet的生命周期,并说出Servlet和CGI的区别。 Servlet被服务器实例化后,容器运行其init方法,...

    超级有影响力霸气的Java面试题大全文档

    java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。 9、说出Servlet的生命周期,并说出Servlet和CGI的区别。  Servlet被服务器实例化后,容器运行其init方法...

    Java虚拟机规范(Java SE 7)

    2.5.5 运行时常量池 .............................................. 30 2.5.6 本地方法栈 ............................................... 30 2.6 栈帧 .........................................................

    Java开发技术大全 电子版

    Java开发技术大全 电子版 第1篇Java基础知识入门. 第1章Java的开发运行环境2 1.1Java的运行环境与虚拟机2 1.2Java的开发环境4 1.2.1JDK的安装4 1.2.2如何设置系统环境变量6 1.2.3编译命令的使用8 1.2.4解释...

Global site tag (gtag.js) - Google Analytics