Java虚拟机知识点-内存分配

本文详细介绍了Java运行时的数据区域,包括程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区等关键概念及其作用。同时,还探讨了HotSpot虚拟机中的对象分配与垃圾回收机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述
1.不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄露和内存溢出问题
二、运行时数据区域
  1. 程序计数器:每个线程都有一个(线程私有);唯一一个没有在Java虚拟机规范中规定任何OutMemoryError的内存区域
  2. Java虚拟机栈:线程私有;描述Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息
  1. 局部变量表:存放了编译期可知的各种基本数据类(boolean,byte,char,short,int,float,long,double)、对象引用和returnAddress类型。所需的内存空间在编译期间完成分配,方法运行期间不会改变局部变量表的大小
  1. 本地方法栈(Native Method Stack):与虚拟机栈的区别在于,虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务
  2. Java堆:虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。用于存放对象实例。是垃圾收集器管理的主要区域。Java规范规定,Java堆的内存空间不需物理上连续,只需逻辑上连续
  3. 方法区:各线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。其内存空间只需逻辑上连续、可以选择固定大小或可扩展、可选择不实现垃圾回收
  4. 运行时常量池:方法区的一部分。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性
  5. 直接内存:使用Native函数库直接分配堆外内存,可通过存储在Java堆中的DirectByteBuffer对象作为这块内存的应用进行操作
三、HotSpot虚拟机对象
  1. 虚拟机遇到一条new指令
  1. 首先检查这个指令的参数是否在常量池中,其代表的类是否已被加载、解析和初始化;若没有,必须先执行相应的类加载过程
  2. 在堆中为对象分配内存
  1. 指针碰撞(Bump the Pointer):指针仅移动与对象大小相等的连续距离
  1. 在使用SerialParNew等带Compact过程的收集器采用
  1. 不能进行指针碰撞,虚拟机就必须维护一个列表来记录哪些内存可用(空闲列表(Free List)
  1. 使用CMS这种基于Mark-Sweep算法的收集器时采用
  1. 并发分配内存-解决
  1. 对分配内存空间的动作进行同步处理
  2. 按线程划分内存空间:本地线程分配缓存(Thread Local Allocation Buffer, TLAB
  1. 将内存空间初始化为零值
  2. 虚拟机对对象进行必要的设置
  1. 对象头(Object Header):存放元数据信息、对象的哈希码、对象的GC分代年龄等
  1. 执行<init>
  1. 对象的内存布局
  1. 对象头
  2. 实例数据:存储对象的有效信息、各类型的字段内容
  1. 从父类继承下来的也要记录
  2. HotSpot虚拟机的默认分配策略:longs/doubles, ints, shorts/chars, bytes/Booleans, oops(Ordinary Object Pointers)
  1. 相同宽度的字段总是被分配到一起
  1. 对齐填充:仅起到占位符的作用
  1. 对象的访问定位
  1. Java程序需要通过栈上的reference数据来操作堆上的具体对象
  2. 对象访问方式:句柄和直接指针
  1. 句柄池:reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息
  1. 对像被移动时只需改变句柄中的实例数据指针,reference本身不需修改
  1. 直接指针:reference存储的是对象地址
  1. 速度较快:不用指针定位
  1. OutOfMemoryError异常
  1. 可能发生的区域:方法区、堆、虚拟机栈、本地方法栈等
  2. Java堆溢出
  1. 存储的对象实例占用的内存达到上限
  2. 参数(-XX:+HeapDumpOnOutOfMemoryError):堆内存满时跳出
  3. 内存映像分析工具:Eclipse Memory Analyzer
  4. 参数在Run configuration中设置
  1. 虚拟机栈和本地方法栈溢出
  1. HotSpot不区分虚拟机栈和本地方法栈;栈参数(-Xss
  2. SatckOverflowError:栈溢出
  3. 扩展栈失败: OutOfMemoryError
  4. 单个线程下,无论是栈帧太大还是虚拟机栈容量太小,当内存无法分配时,虚拟机都会抛出StackOverflowError
  1. 方法区和运行时常量池溢出
  1. 方法区设置参数:-XX:PermSize-XX:MaxPermSize
  2. String.intern():是一个native方法;查看常量池中是否有该String对象,没有则添加到常量池
  3. 字节码技术:如GCLib;保证动态生成的类可以加载到内存
  4. JVM动态语言:如Groovy;实现语言的动态性
  1. 直接内存溢出
  1. 参数(-XX:MaxDirectMemorySize:默认与Java堆最大值一样

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值