JVM内存结构

JVM内存区域分配

在这里插入图片描述

Java堆是各线程共享的内存区域,在jvm启动时创建,这块区域时jvm中最大的,用于存储应用的对象和数组,也是GC主要的回收区,一个jvm实例只存在一个堆内存,堆内存是可以调节的,类加载器读取类文件后,需要把类、方法、常量放到堆内存中,以方便执行器执行,堆内存分为三部分:新生代、老年代、永久代。

Java线程栈私有的,是在线程创建时创建,它的生命周期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,基本类型的变量和对象的引用变量都是在函数的栈内存中分配。

栈帧

每个方法执行都会创建一个栈帧。每个方法都有独立的栈帧内存空间,栈数据结构:先进后出销毁
栈帧内部细节结构:局部变量表、操作数栈、动态链接、方法出口。

  1. 每个运行时所需要的内存,称作为虚拟机栈
  2. 每个栈有多个栈帧组成,对应着每次方法调用时占用的内存
  3. 每个线程只能有一个活动的栈,对应着当前正在执行的方法。

程序计数器

记录当前线程执行下一行指令的执行地址,只有在多线程的时候才起作用。

本地方法栈

本地方法栈和jvm栈发挥的作用非常相似,也是线程私有的,区别是jvm栈为jvm执行Java方法,而本地方法栈为jvm使用到的Native方法服务,是java调用c语言方法。
在这里插入图片描述

栈内存溢出

栈帧没有及时释放,导致栈空间满了,导致栈内存溢出。

方法区(元空间)

常量池

静态常量池、运行常量池、字符串常量池

存放区域

  1. java6和6之前,常量池是存放在方法区中的(永久区,gc不会回收)
  2. java7,将常量池存放到堆中(不合理,gc会回收,有一些全局变量不用回收)
  3. java8之后,取消了整个永久代区域,放在元空间中,运行时常量池和静态常量池存放在元空间中,而字符串常量池依然存放在堆中。

常见的字符串常量面试题

package com.mayikt;

/**
 * @Description:
 * @Author: ChenYi
 * @Date: 2020/08/17 14:19
 **/

public class Test007 {
    public static void main(String[] args) {
        String s1 = "a";
        String s2 = "b";
        String s3 = "a" + "b";
        String s4 = s1 + s2;
        String s5 = "ab";
        //将对象放入字符串常量池中
        String s6 = s4.intern();
        /**
         * 结果为false 因为底层是通过StringBuilder来帮忙拼接的,最后在toString()方法,
         * 通过StringBuilder的toString()方法可以看出是new String()对象的,放在堆内存中的,所以两者是不相等的
         */
        System.out.println(s3 == s4);
        //true
        System.out.println(s3 == s5);
        //true
        System.out.println(s3 == s6);
    }
}

总结
  1. 在字符串常量池中,变量引用方式底层是采用StringBuilder实现的
    参考:蚂蚁课堂
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值