文章目录

  • Pre
  • 示例demo
  • 总体关系
  • 代码示例论证
  • 反汇编

Pre

JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器

中我们探讨了线程栈中的内部结构 ,大家有么有想过main方法呢? 我们继续来看下main方法


示例demo

package com.gof.test;public class Artisan {public static final int FIVE = 5 ; // final静态变public static  User user = new User();// 静态变量public static void main(String[] args) {Artisan artisan = new Artisan();artisan.doSomething();}public int doSomething() {int a = 1 ;int b = 2 ;int c = (a + b) * 10 ;return c;}
}

final对象和static对象 ,我们知道都会存放在方法区(元空间)中的运行时常量池。 User 和 FIVE 会存放在该区域内。

方法区#运行时常量池 ,是方法区的一部分。 Class文件中的常量池表用于存放编译期间生成的各种字面量和符号引用,这部分内容将在类加载后放到方法区的运行时常量池中。


反汇编 ,附带附件信息

 E:\Program Files\Java\jdk1.8.0_161\bin> ./javap -c -v D:\IdeaProjects\GOF23\target\classes\com\gof\test\Artisan.class > Artisan.txt
PS E:\Program Files\Java\jdk1.8.0_161\bin>

可以看到 Constant Pool

 Constant pool:#1 = Methodref          #8.#35         // java/lang/Object."<init>":()V#2 = Class              #36            // com/gof/test/Artisan#3 = Methodref          #2.#35         // com/gof/test/Artisan."<init>":()V#4 = Methodref          #2.#37         // com/gof/test/Artisan.doSomething:()I#5 = Class              #38            // com/gof/test/User#6 = Methodref          #5.#35         // com/gof/test/User."<init>":()V#7 = Fieldref           #2.#39         // com/gof/test/Artisan.user:Lcom/gof/test/User;#8 = Class              #40            // java/lang/Object#9 = Utf8               FIVE#10 = Utf8               I#11 = Utf8               ConstantValue#12 = Integer            5#13 = Utf8               user#14 = Utf8               Lcom/gof/test/User;#15 = Utf8               <init>#16 = Utf8               ()V#17 = Utf8               Code#18 = Utf8               LineNumberTable#19 = Utf8               LocalVariableTable#20 = Utf8               this#21 = Utf8               Lcom/gof/test/Artisan;#22 = Utf8               main#23 = Utf8               ([Ljava/lang/String;)V#24 = Utf8               args#25 = Utf8               [Ljava/lang/String;#26 = Utf8               artisan#27 = Utf8               doSomething#28 = Utf8               ()I#29 = Utf8               a#30 = Utf8               b#31 = Utf8               c#32 = Utf8               <clinit>#33 = Utf8               SourceFile#34 = Utf8               Artisan.java#35 = NameAndType        #15:#16        // "<init>":()V#36 = Utf8               com/gof/test/Artisan#37 = NameAndType        #27:#28        // doSomething:()I#38 = Utf8               com/gof/test/User#39 = NameAndType        #13:#14        // user:Lcom/gof/test/User;#40 = Utf8               java/lang/Object

找下User和 FIVE


总体关系

Note: FIVE 是 final的,上图少写了


代码示例论证

当我们执行main方法

public static void main(String[] args) {Artisan artisan = new Artisan();artisan.doSomething();}

Artisan artisan = new Artisan(); 这个对象会在堆上分配一块内存空间用来存储该对象。

main也是个方法,也得有方法栈, 那方法栈中的局部变量表中存放的artisan是个啥呢? 其实是 对象的引用 ,也就是对象的内存地址 。

这样,线程栈和堆的关系就产生了。

当类在编译阶段,静态类User , 会被分配到方法区 , 那 new User() 存放在 堆中,方法区的User 和 堆中的User 什么关系呢? 引用的关系,方法区中的User仅仅是个符号引用,指向真正的堆内存中的User对象。

这样 方法区和堆的关系就产生了 。


反汇编

Classfile /D:/IdeaProjects/GOF23/target/classes/com/gof/test/Artisan.classLast modified 2020-6-22; size 772 bytesMD5 checksum 89d38013e132ab14203f796617191dd9Compiled from "Artisan.java"
public class com.gof.test.Artisanminor version: 0major version: 52flags: ACC_PUBLIC, ACC_SUPER
Constant pool:#1 = Methodref          #8.#35         // java/lang/Object."<init>":()V#2 = Class              #36            // com/gof/test/Artisan#3 = Methodref          #2.#35         // com/gof/test/Artisan."<init>":()V#4 = Methodref          #2.#37         // com/gof/test/Artisan.doSomething:()I#5 = Class              #38            // com/gof/test/User#6 = Methodref          #5.#35         // com/gof/test/User."<init>":()V#7 = Fieldref           #2.#39         // com/gof/test/Artisan.user:Lcom/gof/test/User;#8 = Class              #40            // java/lang/Object#9 = Utf8               FIVE#10 = Utf8               I#11 = Utf8               ConstantValue#12 = Integer            5#13 = Utf8               user#14 = Utf8               Lcom/gof/test/User;#15 = Utf8               <init>#16 = Utf8               ()V#17 = Utf8               Code#18 = Utf8               LineNumberTable#19 = Utf8               LocalVariableTable#20 = Utf8               this#21 = Utf8               Lcom/gof/test/Artisan;#22 = Utf8               main#23 = Utf8               ([Ljava/lang/String;)V#24 = Utf8               args#25 = Utf8               [Ljava/lang/String;#26 = Utf8               artisan#27 = Utf8               doSomething#28 = Utf8               ()I#29 = Utf8               a#30 = Utf8               b#31 = Utf8               c#32 = Utf8               <clinit>#33 = Utf8               SourceFile#34 = Utf8               Artisan.java#35 = NameAndType        #15:#16        // "<init>":()V#36 = Utf8               com/gof/test/Artisan#37 = NameAndType        #27:#28        // doSomething:()I#38 = Utf8               com/gof/test/User#39 = NameAndType        #13:#14        // user:Lcom/gof/test/User;#40 = Utf8               java/lang/Object
{public static final int FIVE;descriptor: Iflags: ACC_PUBLIC, ACC_STATIC, ACC_FINALConstantValue: int 5public static com.gof.test.User user;descriptor: Lcom/gof/test/User;flags: ACC_PUBLIC, ACC_STATICpublic com.gof.test.Artisan();descriptor: ()Vflags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 4: 0LocalVariableTable:Start  Length  Slot  Name   Signature0       5     0  this   Lcom/gof/test/Artisan;public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=2, args_size=10: new           #2                  // class com/gof/test/Artisan3: dup4: invokespecial #3                  // Method "<init>":()V7: astore_18: aload_19: invokevirtual #4                  // Method doSomething:()I12: pop13: returnLineNumberTable:line 9: 0line 10: 8line 11: 13LocalVariableTable:Start  Length  Slot  Name   Signature0      14     0  args   [Ljava/lang/String;8       6     1 artisan   Lcom/gof/test/Artisan;public int doSomething();descriptor: ()Iflags: ACC_PUBLICCode:stack=2, locals=4, args_size=10: iconst_11: istore_12: iconst_23: istore_24: iload_15: iload_26: iadd7: bipush        109: imul10: istore_311: iload_312: ireturnLineNumberTable:line 13: 0line 14: 2line 15: 4line 16: 11LocalVariableTable:Start  Length  Slot  Name   Signature0      13     0  this   Lcom/gof/test/Artisan;2      11     1     a   I4       9     2     b   I11       2     3     c   Istatic {};descriptor: ()Vflags: ACC_STATICCode:stack=2, locals=0, args_size=00: new           #5                  // class com/gof/test/User3: dup4: invokespecial #6                  // Method com/gof/test/User."<init>":()V7: putstatic     #7                  // Field user:Lcom/gof/test/User;10: returnLineNumberTable:line 6: 0
}
SourceFile: "Artisan.java"

JVM - 结合代码示例彻底搞懂Java内存区域_对象在堆-栈-方法区(元空间)之间的关系相关推荐

  1. JVM - 结合代码示例彻底搞懂Java内存区域_线程栈 | 本地方法栈 | 程序计数器

    文章目录 Pre 运行时数据区总览 线程栈 概要 栈内部主要组成部分 局部变量 操作数栈 动态链接 方法出口 小结 程序计数器 本地方法栈 附 测试demo javap JVM字节码指令集手册 Pre ...

  2. java方法区对象类型_浅谈Java内存区域与对象创建过程

    一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...

  3. 【JVM进阶之路】二:Java内存区域

    1.运行时数据区 Java 虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁.另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线 ...

  4. JVM面试重点总结(一)——java内存区域与内存溢出异常

    1.java内存区域是如何划分的?运行时数据区包含哪几部分? 2.方法.new.类在jvm内存中的产生区域? 3.什么是程序计数器?特点,作用?什么是"线程私有"的内存? 4.介绍 ...

  5. Java虚拟机2:Java内存区域及对象

    几个计算机的概念 为以后写文章考虑,也为巩固自己的知识和一些基本概念,这里要理清楚几个计算机中的概念. 1.计算机存储单位 从小到大依次为位Bit.字节Byte.千字节KB.兆M.千兆GB.TB,相邻 ...

  6. Java 虚拟机:Java 内存区域及对象,java 反射面试

    1.计算机存储单位 从小到大依次为位 Bit.字节 Byte.千字节 KB.兆 M.千兆 GB.TB,相邻单位之间都是 1024 倍,1024 为 2 的 10 次方,即: 1Byte = 8bit ...

  7. java虚拟机-java内存区域和对象(五月的仓颉)

    1.计算机存储单位 从小到大依次为位Bit.字节Byte.千字节KB.兆M.千兆GB.TB,相邻单位之间都是1024倍,1024为2的10次方,即: 1Byte = 8bit 1K = 1024Byt ...

  8. 300 行代码带你搞懂 Java 多线程!

    线程 线程的概念,百度是这样解释的: 线程(英语:Thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可 ...

  9. 彻底搞懂Java内存泄露

    Java内存回收方式 Java判断对象是否可以回收使用的而是可达性分析算法. 在主流的商用程序语言中(Java和C#),都是使用可达性分析算法判断对象是否存活的.这个算法的基本思路就是通过一系列名为& ...

最新文章

  1. 错误3 error C3859: 超过了 PCH 的虚拟内存范围;请使用“-Zm120”
  2. ospf避免环路_OSPF路由协议的区域防环机制
  3. linux只剩 目录挂载,linux(centOS7)的基本操作(五) 磁盘、分区、挂载、卸载
  4. leetcode 896. 单调数列
  5. OpenShift 4.3 - 基于虚拟机的BareMetal离线安装(4)
  6. 【转】VC6下安装与配置OpenCV1.0
  7. 水晶报表攻克系列3-如何在程序中自定义纸张
  8. 整理15款实用javascript富文本编辑器
  9. com词根词缀_【单词杂谈】推荐几个学习英语词根词缀的网站,建议收藏!
  10. 关于使用VS2015编译项目时出现LNK1112 module machine type 'x64' conflicts with target machine type 'X86'
  11. 金融反欺诈常用特征处理方法
  12. Altium Designer中修改敷铜与焊盘间的间距
  13. 计算机程序设计员国家职业资格三级(高级)操作技能考核试卷-四川考场
  14. js map根据value获取key
  15. python之Continuity循环
  16. 一阶导数和二阶导数的一些性质
  17. 洛谷 P3939 数颜色(主席树)
  18. 细解网易宝系统架构之高可用篇
  19. ENDNOTE中使用Adobe打开PDF后提示“只读无法保存”
  20. 南方究竟有没有冬天?

热门文章

  1. java 之在校期间最后一次实训记录
  2. kib,mib和mb,kb的区别
  3. python 调用支付宝微信接口_前端在h5页面调起微信支付接口和支付宝接口(日常笔记)...
  4. java 学习(一)冒泡排序
  5. pythonsvm图像分类_python图像处理之sift-kmeans-SVM图像分类
  6. linux scp远程拷贝文件及文件夹
  7. 强化学习(一)---绪论
  8. toch_geometric 笔记:message passing GCNConv
  9. MATLAB从入门到精通-以实例的形式带你玩转Matlab三角函数
  10. 听说你想去大厂看妹子,带你看看腾讯产品运营岗超详细面经