java学习笔记-内存分布-方法区/元空间

目录

栈、堆、方法区的交互关系

方法区的理解

设置方法区内存的大小

方法区的内部结构

概述

类型信息

域信息(Field)

方法信息

静态变量

常量池表和运行时常量池

比较

常量池表

运行时常量池

总结:方法区存储了什么

方法区历代版本的演进

历代版本图

为什么要把永久代换成元空间?

StringTable为什么要调整

方法区的垃圾回收

 


 

 

栈、堆、方法区的交互关系

  • 运行时数据区结构图

  •  我们学习的HotSpot用的是左图这种直接指针的方式,但是还有一种句柄池的方式(《深入理解Java虚拟机》),如右图所示

方法区的理解

  • JDK1.7之前方法区又叫永久代PermGen space,1.7之后叫做元空间Metaspace, 元空间使用的是本地内存,不使用jvm的内存。

 

设置方法区内存的大小

  • jdk7之后这个指令是无效的,因为已经替换成元空间了

  • jdk8及以后都是设置元空间命令 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 指定

方法区的内部结构

概述

  • 字节码文件如下
D:\buildproject\jvm-study\out\production\jvm-01\com\vuhen\jvmMethod>javap -v -p  MethodDemo.class
Classfile /D:/buildproject/jvm-study/out/production/jvm-01/com/vuhen/jvmMethod/MethodDemo.class
  Last modified 2021-5-12; size 1095 bytes
  MD5 checksum 0f0987d697ef358a1a47c75699f74abf
  Compiled from "MethodDemo.java"

//类型信息
public class com.vuhen.jvmMethod.MethodDemo extends java.lang.Object implements java.util.Comparator<java.lang.String>
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
//常量池
Constant pool:
   #1 = Methodref          #8.#38         // java/lang/Object."<init>":()V
   #2 = Fieldref           #7.#39         // com/vuhen/jvmMethod/MethodDemo.publicVal:I
   #3 = Fieldref           #7.#40         // com/vuhen/jvmMethod/MethodDemo.priVal:I
   #4 = Class              #41            // java/lang/String
   #5 = Methodref          #7.#42         // com/vuhen/jvmMethod/MethodDemo.compare:(Ljava/lang/String;Ljava/lang/String;)I
   #6 = Fieldref           #7.#43         // com/vuhen/jvmMethod/MethodDemo.priStaticVal:I
   #7 = Class              #44            // com/vuhen/jvmMethod/MethodDemo
   #8 = Class              #45            // java/lang/Object
   #9 = Class              #46            // java/util/Comparator
  #10 = Utf8               publicVal
  #11 = Utf8               I
  #12 = Utf8               priStaticVal
  #13 = Utf8               priVal
  #14 = Utf8               <init>
  #15 = Utf8               ()V
  #16 = Utf8               Code
  #17 = Utf8               LineNumberTable
  #18 = Utf8               LocalVariableTable
  #19 = Utf8               this
  #20 = Utf8               Lcom/vuhen/jvmMethod/MethodDemo;
  #21 = Utf8               compare
  #22 = Utf8               (Ljava/lang/String;Ljava/lang/String;)I
  #23 = Utf8               o1
  #24 = Utf8               Ljava/lang/String;
  #25 = Utf8               o2
  #26 = Utf8               priMethod
  #27 = Utf8               (I)I
  #28 = Utf8               a
  #29 = Utf8               i
  #30 = Utf8               b
  #31 = Utf8               publicStaticMethod
  #32 = Utf8               (Ljava/lang/Object;Ljava/lang/Object;)I
  #33 = Utf8               <clinit>
  #34 = Utf8               Signature
  #35 = Utf8               Ljava/lang/Object;Ljava/util/Comparator<Ljava/lang/String;>;
  #36 = Utf8               SourceFile
  #37 = Utf8               MethodDemo.java
  #38 = NameAndType        #14:#15        // "<init>":()V
  #39 = NameAndType        #10:#11        // publicVal:I
  #40 = NameAndType        #13:#11        // priVal:I
  #41 = Utf8               java/lang/String
  #42 = NameAndType        #21:#22        // compare:(Ljava/lang/String;Ljava/lang/String;)I
  #43 = NameAndType        #12:#11        // priStaticVal:I
  #44 = Utf8               com/vuhen/jvmMethod/MethodDemo
  #45 = Utf8               java/lang/Object
  #46 = Utf8               java/util/Comparator
{
  //成员变量 域信息
  public int publicVal;
    descriptor: I //类型int
    flags: ACC_PUBLIC //修饰符public

  private static int priStaticVal;
    descriptor: I //类型int
    flags: ACC_PRIVATE, ACC_STATIC //修饰符private,static

  private int priVal;
    descriptor: I//类型int
    flags: ACC_PRIVATE //修饰符private

  //构造器
  public com.vuhen.jvmMethod.MethodDemo();
    descriptor: ()V //()表示参数为空 V表示返回值为void
    flags: ACC_PUBLIC //修饰符public
    Code:
      //栈深度(栈执行中最大的长度);局部变量表的大小;参数个数
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: iconst_5
         6: putfield      #2                  // Field publicVal:I
         9: aload_0
        10: iconst_3
        11: putfield      #3                  // Field priVal:I
        14: return
      LineNumberTable:
        line 5: 0
        line 6: 4
        line 8: 9
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      15     0  this   Lcom/vuhen/jvmMethod/MethodDemo;

  //方法信息
  public int compare(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)I //参数String;String 返回值int
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=3
         0: iconst_0
         1: ireturn
      LineNumberTable:
        line 11: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       2     0  this   Lcom/vuhen/jvmMethod/MethodDemo;
            0       2     1    o1   Ljava/lang/String;
            0       2     2    o2   Ljava/lang/String;

  public int priMethod(int);
    descriptor: (I)I //参数int 返回值int
    flags: ACC_PUBLIC //修饰符public
    Code:
      stack=2, locals=4, args_size=2
         0: iconst_5
         1: istore_2
         2: iconst_4
         3: istore_3
         4: iload_2
         5: iload_3
         6: iadd
         7: iload_1
         8: iadd
         9: ireturn
      LineNumberTable:
        line 15: 0
        line 16: 2
        line 17: 4
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      10     0  this   Lcom/vuhen/jvmMethod/MethodDemo;
            0      10     1     a   I
            2       8     2     i   I
            4       6     3     b   I

  public static void publicStaticMethod();
    descriptor: ()V //无参数无返回值
    flags: ACC_PUBLIC, ACC_STATIC //修饰符public static
    Code:
      stack=1, locals=1, args_size=0
         0: iconst_5
         1: istore_0
         2: return
      LineNumberTable:
        line 21: 0
        line 22: 2
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2       1     0     i   I

  public int compare(java.lang.Object, java.lang.Object);
    descriptor: (Ljava/lang/Object;Ljava/lang/Object;)I //参数Object,Object 返回值int
    flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC //修饰符
    Code:
      stack=3, locals=3, args_size=3
         0: aload_0
         1: aload_1
         2: checkcast     #4                  // class java/lang/String
         5: aload_2
         6: checkcast     #4                  // class java/lang/String
         9: invokevirtual #5                  // Method compare:(Ljava/lang/String;Ljava/lang/String;)I
        12: ireturn
      LineNumberTable:
        line 5: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      13     0  this   Lcom/vuhen/jvmMethod/MethodDemo;

  static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: iconst_4
         1: putstatic     #6                  // Field priStaticVal:I
         4: return
      LineNumberTable:
        line 7: 0
}
Signature: #35                          // Ljava/lang/Object;Ljava/util/Comparator<Ljava/lang/String;>;
SourceFile: "MethodDemo.java"

类型信息

域信息(Field)

方法信息

静态变量

  • 静态变量是和类绑定在一起的,即使没有实例也能够访问,下面的代码是能运行的,不会报错
  • 注:静态变量仍存放在堆中

常量池表和运行时常量池

比较

  • 常量池表是字节码的一部分,运行时常量池是方法区的一部分 常量池表中的内容会在类加载完后放到运行时常量池中
  • 在运行后就会生成运行时常量池,而字节码中的常量池表可以理解为就是运行时常量池中信息的索引

常量池表

  • 一个小小的类里面其实使用了非常多的引用和类,但是下面生成的字节码却非常小,原因就是因为有常量池表,用来存储对类型、域和方法符号引用以及各种字面量

  • 下面这个字节码的大小就说明了常量池表的存在

  • 如下图所示,方法执行时都是调用常量池表的符号引用,符号引用再到常量池中找信息

  • ldc最终找到的常量池中信息就是ceshi1 这个称为字面量

运行时常量池

  • 常量池表在类加载后就会把信息全部都加载到运行时常量池;运行时常量池时具有动态性的 运行期间也可能产生新的常量,这些常量被放在运行时常量池中。

总结:方法区存储了什么

  • 像什么常量池啊,类信息,域信息,方法信息,方法中的指令信息等等都是存在方法区的

方法区历代版本的演进

历代版本图

  • JDK8之前方法区用的还是虚拟机的内存,8及以后用的就是本地内存了
  • StringTable指的是字符串常量池

为什么要把永久代换成元空间?

StringTable为什么要调整

方法区的垃圾回收

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法: 算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值