JAVA int a = 1 中发生了什么
[ToC]
JAVA int a = 1 中发生了什么
测试代码
javac TestCode.java
public class TestCode {
public static void main(String[] args) {
int aaaa = 1;
aaaa = 2;
}
}
反编译 javap -v -p -l TestCode(l是小写的L)
注解:javap是jdk自带的反解析工具。作用是根据class字节码文件,反解析出当前类对应的code区(汇编指令)、本地变量表、异常表和代码行偏移量映射表、常量池等等信息。
Classfile xxxxx/com/code/baseCode/TestCode.class
Last modified 2021-11-21;
size 436 bytes
MD5 checksum c2864ab4f514372ff51ed92e384bb437
Compiled from "TestCode.java"
public class com.code.baseCode.TestCode
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref#3.#19// java/lang/Object."":()V
#2 = Class#20// com/code/baseCode/TestCode
#3 = Class#21// java/lang/Object
#4 = Utf8
#5 = Utf8()V
#6 = Utf8Code
#7 = Utf8LineNumberTable
#8 = Utf8LocalVariableTable
#9 = Utf8this
#10 = Utf8Lcom/code/baseCode/TestCode;
#11 = Utf8main
#12 = Utf8([Ljava/lang/String;
)V
#13 = Utf8args
#14 = Utf8[Ljava/lang/String;
#15 = Utf8aaaa
#16 = Utf8I
#17 = Utf8SourceFile
#18 = Utf8TestCode.java
#19 = NameAndType#4:#5// "":()V
#20 = Utf8com/code/baseCode/TestCode
#21 = Utf8java/lang/Object
{
public com.code.baseCode.TestCode();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1// Method java/lang/Object."":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
StartLengthSlotNameSignature
050thisLcom/code/baseCode/TestCode;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;
)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=2, args_size=1
0: iconst_1
1: istore_1
2: iconst_2
3: istore_1
4: return
LineNumberTable:
line 11: 0
line 12: 2
line 52: 4
LocalVariableTable:
StartLengthSlotNameSignature
050args[Ljava/lang/String;
231aaaaI
}
SourceFile: "TestCode.java"
反编译后,会发现aaaa存在于Constant pool(常量池)和LocalVariableTable(本地变量表)中
常量池解释 JVM中有Class常量池、运行时常量池、全局字符串常量池、基本类型包装类常量池。
- Class常量池:主要存放字面量和符号引用。 详情可看https://vitzhou.top/20200821/
- 字面量就是固定值,int a = 1,String a = "abc",其中1和abc就是字面量,但java中字面量必须是final修饰
- 由于在编译过程中并不知道每个类的地址,因为可能这个类还没有加载,所以如果你在一个类中引用了另一个类,那么你完全无法知道他的内存地址,那怎么办,我们只能用他的类名作为符号引用,在类加载完后用这个符号引用去获取他的内存地址。
- 运行时常量池:运行时常量池部分数据是来自于Class常量池,其具有动态性。在Class常量池中存储着字面量和符号引用,其中符号引用会在加载时,将Class中字节流代表的静态存储转换为方法区的运行时数据结构。不同的类用同一个运行时常量池。
- 字符串常量池:JVM所维护的一个字符串实例的引用表。运行时常量池在方法区中,JDK1.7后,字符串常量池移到了堆中。
- java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外上面这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。
https://juejin.cn/post/685457...
https://juejin.cn/post/699736...
【JAVA int a = 1 中发生了什么】jvm中class文件常量池中存放了哪些信息?/常量池为什么有变量名称呢?
https://blog.csdn.net/Hellowe...
https://www.jianshu.com/p/cf7...
局部变量表和操作数栈?
https://www.jianshu.com/p/a6a...
图片解释 java1.8的内存布局
文章图片
在编译后内存情况
类文件结构:https://juejin.cn/post/688335...
文章图片
运行时发生情况
其中java byte code为
如何查看Java bytecode指令?
https://en.wikipedia.org/wiki...
http://gityuan.com/2015/10/24...
文章图片
上面注意的地方是,变量1指的是LocalVariableTable中的第一个变量,也就是aaaa。
iconst_1
文章图片
istore_1
文章图片
iconst_2
文章图片
istore_1
文章图片
结尾 上述是基础数据类型的情况,后续出String类型,以及包装类型的情况
本文由博客一文多发平台 OpenWrite 发布!
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募