内存结构

本文详细介绍了Java虚拟机的内存结构,包括程序计数器、虚拟机栈、本地方法栈、堆和方法区。重点讨论了各区域的作用、特点、内存溢出情况以及诊断方法。特别提到了字符串常量池、StringTable的特性和优化,以及直接内存的使用和管理。
摘要由CSDN通过智能技术生成

1.程序计数器(Program Counter Register)

        1-1.作用

        记住下一条jvm指令的执行地址

        1-2.特点

                ①.线程私有

                ②.不存在内存溢出

2.虚拟机栈(Java Virtual Machine Stack)  

        2-1.定义

        每个线程运行时需要的内存空间

        组成内容:栈帧(每个方法运行时需要的内存;对应方法的调用)

        每个线栈只能有一个活动栈帧(线程正在执行的方法),对应着当前正在执行的那个方法

        问题解析:

                ①.垃圾回收不涉及栈内存

                ②.栈内存不是越大越好

                ③.线程共享需要考虑线程安全,线程私有不需要考虑线程安全;如果方法内局部变量没有逃离方法的作用范围就是线程安全的,当作返回值就需要保护;如果局部变量引用了对象,并逃离了方法的作用方法,需要考虑线程安全

        2-2.栈内存溢出

                ①.栈帧过多导致栈内存溢出

                ②.栈帧过大导致栈内存溢出

        2-3.线程运行诊断

                ①.cpu占用过多

                定位:

                A.top定位哪个进程对cpu的占用过高

                B.[ps H -eo pid,tid,%cpu|grep进程id(用ps命令进一步定位哪个线程引用的cpu占用过高)];

                C.jstack进程id(根据线程id找到有问题的线程,进一步定位到问题代码的源码行数)

                ②.程序运行很长时间没有结果

3.本地方法栈(Native Method Stacks)

        定义:为本地方法的运行提供一个内存空间

4.堆(Heap)

        4-1.定义

        通过new关键字,创建对象都会使用堆内存

        4-2.特点

        它是线程共享的,堆中对象都需要考虑线程安全问题

        有垃圾回收机制

        4-3.堆内存的溢出

        内存过大时,不容易暴露内存溢出;排查堆内存问题时,把内存的值设置小一点

        4-4.堆内存诊断

        ①.jps工具

        查看当前系统中有哪些java进程

        ②.jmap工具

        查看堆内存占用情况(加上 -heap进程id )

        ③.jconsole工具

        图形界面的,多功能检测工具,可以连续检测

        垃圾回收后,内存占用依然很高

        jvisualvm与jconsole相似

5.方法区 

        5-1.定义

        是JVM线程的方法共享区,存储和类结构相关的信息,包括:成员变量、方法数据、成员和构造器代码和运行时常量池

        方法区在虚拟机启动时创建;逻辑上,方法区是堆的组成部分;规范不强制执行用于管理编译代码的方法区

        5-2.组成

        5-3.方法区内存溢出

        1.8之前会导致永久代内存溢出

演示永久代内存溢出:java.lang.OutOfMemoryError:PermGen space
-XX:MaxPermSize=8m

        1.8之后会导致元空间内存溢出

演示元空间内存溢出:java.lang.OutOfMemoryError:Metaspace
-XX:MatespaceSize=8m

        应用场景:

        ①.spring        

        ②.mybatis

        5-4.运行时常量池

        常量池:是一张表,虚拟机根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息(给指令提供一些常量符号,以查表的方式查找)

        运行时常量池:是.class文件中的,当被类加载,它的常量池信息会被放入运行时常量池,并把里面的符号地址变为真实地址   

        5-5.StringTable特性

        ①.常量池中的字符串仅是符号,第一次用到时才变为对象

        ②.利用串池的机制,避免重复创建字符串对象

        ③.字符串变量拼接的原理是StringBuilder(1.8)

        ④.字符串常量拼接的原理是编译期优化

        ⑤.可以使用intern方法,主动将串池中还没有的字符串对象放入串池

        5-6.StringTable位置

        ①.1.8用的是堆空间

        ②.1.6用的是永久代

        5-7.StringTable垃圾回收 

        5-8.StringTable性能调优

        ①.调整-XX:StringTableSize=桶个数

        ②.考虑将字符串对象是否入池

6.直接内存

        6-1.定义

        ①.常见于NIO操作时,用于数据缓冲区

        ②.分配回收成本较高,但读写性能高

        ③.不受JVM内存回收管理

        6-2.分配和回收原理

        ①.使用Unsafe对象完成直接内存的分配回收,并且回收需要主动调用freeMemory方法

        ②.ByteBuffer的实现类内部,使用了Cleaner(虚引用)来检测ByteBuffer对象,一旦ByteBuffer对象被垃圾回收,那么就会由ReferenceHandler线程通过Cleaner的方法调用freeMemory来释放直接内存

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值