JVM性能优化------内存结构原理分析(一)

前面我们了解了类加载器,类加载器是把class文件读取到jvm虚拟机内存中去。
那么我们的java虚拟机内存结构是怎样的呢?
我们来看这张图片。
在这里插入图片描述

  1. 堆(JMM主存)
    用于存放new出的对象、数组
    有垃圾回收机制
    多线程共享,所以存在线程安全问题
  2. 虚拟机栈(JMM 本地空间/工作内存/主内存的副本数据)
    存放局部变量、栈帧(记录方法信息、当方法执行结束之后或者抛出异常的情况,栈帧空间销毁)、栈操作
    这里面主要的是栈帧空间(局部变量、操作数栈、动态链接、方法地址(方法出口))
    虚拟机栈也叫线程栈、每个线程都有自己独立的栈,互不影响
    多线程不共享
  3. 本地方法栈
    java代码调用C语言代码,也称作jni
    底层使用C写的方法,比如:CAS原子类、 线程Thread
  4. 方法区(1.8之前叫元空间)
    存放类的信息、常量、静态变量、运行时常量
    多线程共享
  5. 程序计数器(PC寄存器)
    只有在多线程中有作用,在多线程的情况下,记录当前线程执行的行号,便于上下文切换
  6. 类加载器
    读取class文件读取到jvm虚拟机内存

在这里重点提一下,栈帧。

了解栈帧之前,我们需要理解一下,栈是一个先进后出的数据结构,是限定仅在表尾进行插入或删除操作的线性表。

那什么是栈帧(Stack Frame)呢?

每一次函数的调用,都会在调用栈(call stack)上维护一个独立的栈帧(stack frame).每个独立的栈帧一般包括:

函数的返回地址和参数
临时变量: 包括函数的非静态局部变量以及编译器自动生成的其他临时变量
函数调用的上下文
栈是从高地址向低地址延伸,一个函数的栈帧用ebp 和 esp 这两个寄存器来划定范围.ebp 指向当前的栈帧的底部,esp 始终指向栈帧的顶部;
ebp 寄存器又被称为帧指针(Frame Pointer);
esp 寄存器又被称为栈指针(Stack Pointer);

具体的体现在哪?
示例代码:

/**
 * @author 龙小虬
 * @date 2021/4/12 15:43
 */
public class Main {

    public void test01(){
        test02();
    }

    public void  test02(){
        System.out.println("02");
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.test01();
    }
}

在这里插入图片描述
这就是我们的栈帧,它首先存储了main,在存储test01,在存储test02,一旦test02结束,那么就会执行test01,栈帧只有在方法全部执行完,或者抛出了全局异常,才会销毁。

还有一个程序计数器
程序计数器
主要作用在多线程的情况中,有很明显的案例。在单核系统中,开了两个线程,线程1,线程2。线程1运行了十秒,运行到了第n行,休眠,线程2运行,这时候程序计数器就将线程一所运行到的行数,记录下来,在下次线程唤醒的时候继续执行。

注意:
这里记录的行数,并不是我们高级语言的代码的行数,而是汇编文件的行数。
那我们怎么才能看到汇编代码呢?其实java命令有自带的编译命令:javap -c -v class文件地址

使用SpiService03.class文件进行反汇编。
编译前:

package com.lxq.impl;

import com.lxq.SpiService;

public class SpiService03 implements SpiService {
    public SpiService03() {
    }

    public String output() {
        return "热部署进行中";
    }
}

命令:javap -c -v C:\xxx\SpiService03.class

  Last modified 2021-4-12; size 428 bytes
  MD5 checksum 49e757dc0f2f2e1a2ba161b862dfbb63
  Compiled from "SpiService03.java"
public class com.lxq.impl.SpiService03 implements com.lxq.SpiService
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #4.#17         // java/lang/Object."<init>":()V
   #2 = String             #18            // 热部署进行中
   #3 = Class              #19            // com/lxq/impl/SpiService03
   #4 = Class              #20            // java/lang/Object
   #5 = Class              #21            // com/lxq/SpiService
   #6 = Utf8               <init>
   #7 = Utf8               ()V
   #8 = Utf8               Code
   #9 = Utf8               LineNumberTable
  #10 = Utf8               LocalVariableTable
  #11 = Utf8               this
  #12 = Utf8               Lcom/lxq/impl/SpiService03;
  #13 = Utf8               output
  #14 = Utf8               ()Ljava/lang/String;
  #15 = Utf8               SourceFile
  #16 = Utf8               SpiService03.java
  #17 = NameAndType        #6:#7          // "<init>":()V
  #18 = Utf8               热部署进行中
  #19 = Utf8               com/lxq/impl/SpiService03
  #20 = Utf8               java/lang/Object
  #21 = Utf8               com/lxq/SpiService
{
  public com.lxq.impl.SpiService03();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/lxq/impl/SpiService03;

  public java.lang.String output();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: ldc           #2                  // String 热部署进行中
         2: areturn
      LineNumberTable:
        line 12: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       3     0  this   Lcom/lxq/impl/SpiService03;
}

如果想了解怎么看汇编语言,可以找博主拿取汇编指令文件。

最后我们就来总结一下线程jvm空间:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙小虬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值