常量池:字节码文件内部包含了常量池
静态常量池:就是静态的概念,和上述常量池一个概念,只是叫法不同
运行时常量池:就是把常量池加载到jvm的方法区,将符号引用转化为直接引用的过程,这时就称为是运行时常量池
成员变量:就是位于类中方法外,位于堆中(例如int i = 3)
实例变量:和成员变量一样,只是叫法不同
静态变量:static修饰的成员变量(实例变量),jdk1.7及之后位于堆中
类变量:和静态变量一样,只是叫法不同
核心理解:
以下是我查网上资料和看书看视频个人总结的不一定对,有啥不对的地方请各位大佬在评论区指教,互相学习探讨。如果这篇文章对你有用,希望可以点个大大的赞!!
javap -v -p反编译.class字节码文件有个Constant pool就是常量池,常量池是放在字节码文件中的,类加载器加载完类文件后,把一些类信息、域信息以及字面量、符号引用等内容加载到方法区的运行时常量池。形象的说就是字节码文件中的常量池相当于菜谱,而运行时常量池就相当于把菜谱转化为原材料。静态变量和字符串常量池在jdk1.7的时候移动到了堆中。比如static int i = 3这样一个静态成员变量jdk1.7及之后是存放在堆中的,之前就在永久代里面。static修饰的变量在准备阶段赋值为0,类初始化时赋值为3。而运行时常量池一直在方法区当中,方法区是规范,而永久代和元空间是它的实现。jdk1.8之前是永久代,jdk1.8就变为了元空间,元空间使用的是本地内存。比如final int i = 3这样一个成员变量,它就存储于运行时常量池中,jdk1.8及之后就一直放在元空间中。那么有人想问了static final int i = 3放在哪儿呢?我个人理解的是放在堆中(以jdk1.7及之后为例说明),static修饰的变量叫静态变量,而static是在类加载过程的准备阶段时候进行分配内存以及赋值操作,也就是说,准备阶段分配内存的时候就已经在堆中分配了内存,因为jdk1.7及之后静态变量是存放于堆中的。final修饰只是说明了在准备阶段就赋值为3而不是0(来源于深入理解Java虚拟机第三版第272页)。final修饰的变量一旦被赋值就不能再被更改。对了,static不能修饰局部变量。还有一种情况就是如果final int i = 3位于方法里,也就是它作为局部变量出现的话,如果只写final int i而没有去赋值的话,那么不会报红,而全局变量就会报红。但是使用前都必须进行显示赋值,不然的话还是会报错的。例如下图所示; 然后final int i是位于栈中的,指向运行时常量池中的3这个字面量。