JVM内存分配样例

JVM系列之内存分配与回收策略 前言 经过前面几篇文章,我们已经对JVM虚拟机有了个初步认识,也了解了各区域应用哪些收集器,以及每个收集器用哪些收集算法,但是在这一系列过程中,其实就是一个对象的由生到死的过程,那么在这过程中对象是怎么处理它的生命周期的呢,今天我们就来介绍下对象在内存中的分配和回收分配给对象的内存,那么,让我们带着愉快的周末心情来开启今天的JVM之旅吧。 内存分配 内存分配,通俗讲就是对象在堆上分配:对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先在TLAB上分配。少数对象也可能直接. 阅读详情

JVM内存分配

使用对JVM不同内存区域灌入数据,导致相关区域内存溢出,来验证JVM内存分配
先看一个经典问题:

String s1 = "小金子(aub)";  
String s2 = "小金子(aub)";  
String s3 = "小金子" + "(aub)";  
String s4 = new String("小金子(aub)");  
String s5 = "小金子" + new String("(aub)");  
String s6 = s4.intern();  
System.out.println("s1 == s2: " + (s1 == s2));//true;  
System.out.println("s1 == s3: " + (s1 == s3));//true;  
System.out.println("s2 == s3: " + (s2 == s3));//true;  
System.out.println("s1 == s4: " + (s1 == s4));//false;  
System.out.println("s1 == s5: " + (s1 == s5));//false;  
System.out.println("s4 == s5: " + (s4 == s5));//false;  
System.out.println("s1 == s6: " + (s1 == s6));//true;  

原因就在与String对象特殊的内存分配方式:(Strings pool是JVM内存中运行时常量池的一部分)
1. String s1 = new String(“小金子(aub)”);
2. String s2 = “小金子(aub)”;
3. String s3 = “小金子” + “(aub)”;
虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。
对于第一种,jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。
对于第二种,jvm首先会在内部维护的strings pool中通过String的 equels 方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。
注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法
对于第三种,jvm会进行“+”运算符号的优化,两遍都是字符串常量会做类似于第二种的处理,如果“+”任意一边是一个变量,就会做类似第一种的处理。

1.1 JVM栈和Native Method栈内存分配:

JAVA中八个基本类型数据,在运行时都是分配在栈中的。在栈上分配的内存,随着数据的进栈出栈,方法运行完毕,或则线程结束时,自动被回收掉了。
测试代码如下:

public class JvmStackOOM {  
    private int stackLength = 1;  

    public void execute() {  
        try {  
            stackLeak();  
        } catch (Throwable e) {  
            System.out.println("stackLength : " + stackLength);  
            e.printStackTrace();  
        }  
    }  

    private void stackLeak() {  
        stackLength++;  
        stackLeak();  
    }  
}  

用一个递归不断地对实例变量stackLength进行自增操作,当JVM在扩展栈时无法申请到足够的空间,将产生StackOverflowError
可以使用Jvm 参数-Xss配置栈大小,例如:-Xss2M,栈内存越大,可的栈深度越大,在内存不变的情况下,jvm可创建的线程就越少,需要合理设置。

1.2 方法区内存分配:

类信息和运行时常量将会分配到此区域。
测试代码如下:

public class JvmRuntimeConstantPoolOOM {  
    private int runtimeConstantCount = 1;  

    public void execute() {  
        try {  
            runtimeConstantLeak();  
        } catch (Throwable e) {  
            System.out.println("runtimeConstantCount : " + runtimeConstantCount);  
            e.printStackTrace();  
        }  
    }  

    private void runtimeConstantLeak() {  
        List<String> list = new ArrayList<String>();  
        while (true) {  
            list.add(String.valueOf(runtimeConstantCount++).intern());  
        }  
    }  
}  

使用String的intern()方法向方法区中灌入数据,当方法区内存不足时,抛出OutOfMemoryError: PermGen space,
也可以加载过多的类的方式,测试是否有OutOfMemoryError: PermGen space异常,如果有说明类信息也是存放在方法区中的可以
使用Jvm 参数-XX:PermSize和-XX:MaxPermSize配置栈大小,例如:-XX:PermSize=10M -XX:MaxPermSize=10M

1.3 堆内存分配:

所有对象实例及数组都会在堆上分配。
堆分为新生代和老年代。新生代分为3个区域:一个eden区,和两个survivor区(互为From、To,相对的),
新建对象时首先想eden区申请分配空间,如果空间够,就直接进行分配,否则进行一次Minor GC(新生代垃圾回收)。
Minor GC后再次尝试将对象放到eden区,如果空间仍然不够,直接在老年代创建对象。
测试代码如下:

public class JvmHeapOOM {  
    private int bojectCount = 1;  

    public void execute() {  
        try {  
            heapLeak();  
        } catch (Throwable e) {  
            System.out.println("bojectCount : " + bojectCount);  
            e.printStackTrace();  
        }  
    }  

    private void heapLeak() {  
        List<OOMObject> list = new ArrayList<OOMObject>();  
        while (true) {  
            list.add(new OOMObject());  
            bojectCount++;  
        }  
    }  

    private class OOMObject {  

    }  
} 

创建多个OOMObject对象放到List中,当堆内存不足时,产生OutOfMemoryError:Java Heap space
使用Jvm 参数-Xm -Xmx -Xmn -XX:SurvivorRatio配置堆,例如:-Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8

1.4 本地直接内存分配:

堆外内存,NIO相关操作将在此分配内存
使用Jvm 参数-XX:MaxDirectMemorySize配置,例如:-XX:MaxDirectMemorySize=10M

1.5 所有用到的JVM启动参数:

-Xss2M 设置JVM栈内存大小
-Xms20M 设置堆内存初始值
-Xmx20M 设置堆内存最大值
-Xmn10M 设置堆内存中新生代大小
-XX:SurvivorRatio=8 设置堆内存中新生代Eden 和 Survivor 比例
-XX:PermSize=10M 设置方法区内存初始值
-XX:MaxPermSize=10M 设置方法区内存最大值
-XX:MaxDirectMemorySize=10M 设置堆内存中新生代大小

JVM 内存分配性能问题 JVM内存分配不合理会导致频繁GC,影响系统吞吐量和响应时间。文章通过模拟抢购接口的压力测试,发现高并发下堆内存不足引发FullGC问题。通过分析GC日志,调整-Xms和-Xmx参数增大堆内存后,系统吞吐量提升40%,响应时间降低50%。建议结合具体业务场景,通过监控GC日志持续优化JVM内存配置,以提升系统性能。 阅读详情

相关推荐

Palantir解密:从企业数字化能力构成说起,“本体”如何破解现代企业数据应用难题?

抛开技术外壳来看,Palantir“本体”的理念内核其实并不复杂:构建一个统一、可操作的数字现实,以高效驱动决策与行动。其技术实施和产品沉淀的过程诚然是高复杂性、高难度的,但这正体现了Palantir所代表的新硅谷“All in AI+”的战略决心。对于我们而言,必须深刻认识到:企业数字化能力建设既不是高精尖技术的简单堆砌,也不是局部场景的数字化改良,而是一场企业级的“数字孪生”——关乎战略、组织与业务全域的体系能力的重塑。

SZSDQJC的博客 1685

《深入理解Java虚拟机》读后总结(二)JVM内存分配

《深入理解Java虚拟机》读后总结 (一)Sun HotSpot JVM内存模型 (二)Sun HotSpot JVM内存分配 (三)Sun HotSpot JVM内存监控 (四)Sun HotSpot JVM垃圾回收   基于Sun HotSpot JVM  请先了解JVM内存模型在来看此篇文章 使用对JVM不同内存区域灌入数据,导致相关区域内存溢出,来...

忘掉地平线 189

【ORB_SLAM系列4】—— 一文搞定如何在Ubuntu20.04中安装运行ORB_SLAM3(包含ROS版本和非ROS版本)

ORB-SLAM3是一款基于特征点的实时单目SLAM系统,是SLAM领域的研究热点之一。它的核心算法是结合了ORB特征点提取和描述子匹配、单目RGB相机的深度估计、运动估计和地图优化等步骤,能够在实时性和精度之间取得平衡,适用于各种环境下的定位和建图任务。在各种应用领域都有广泛的应用。本教程主要是介绍了关于在ubuntu20.04中运行ORB_SLAM3的所有依赖的库的安装过程,和所遇到的一些报错的解决方法。有什么问题,可以评论区里面交流讨论

2401_82458959的博客 5039

jvm 对象实例详解

文章目录1 对象实例化1.1 创建对象的方式1.2 字节码角度查看创建对象1.3 对象创建的步骤1.3.1 判断对象对应的类是否加载,链接,初始化1.3.2 为对象分配内存1.3.3 处理并发安全问题1.3.4 初始化分配到的空间1.3.5 设置对象的对象头1.3.6 执行init方法进行初始化2 对象的内存布局2.1 对象头2.2 实例数据2.3 对齐填充3 对象访问定位3.1 句柄访问3.2 直接指针(hotspot采用) 1 对象实例化 1.1 创建对象的方式 new 变形1:XXX的静态方法 变

ytsydmx的博客 642

若依Vue整合积木报表实战:Token安全校验全流程解析

本文详细解析了在若依Vue后台系统中安全集成积木报表的全流程,重点阐述了Token安全校验的核心机制。通过前端菜单配置、Token传递、后端权限拦截及自定义Token服务实现,构建了一套完整的企业级报表访问安全防线,确保核心业务数据的安全可控。

t8u9v0的博客 576

NXP S32K1 SPI驱动实战:从配置到DMA传输的完整流程解析

本文深入解析了NXP S32K1系列MCU的SPI驱动开发全流程。基于S32 Design Studio环境,详细阐述了从引脚配置、LPSPI模块初始化,到实现阻塞、中断及DMA三种传输模式的实战代码与配置要点。文章重点剖析了DMA传输的配置细节与性能优化,旨在帮助开发者构建高效、稳定的嵌入式SPI通信,并提供了SPI Flash驱动的综合案例。

blue42的博客 712

深入JVM了解Java对象实例化过程

加载类元信息为对象分配内存处理并发问题属性的默认初始化(零值初始化)设置对象头信息属性的显示初始化、代码块中初始化、构造器中初始化在没有继承的条件下,实例化一个对象初始化的顺序为:静态成员的初始化静态初始化块成员的初始化初始化块构造器这里面需要注意的是【静态部分只在类加载时初始化一次】如果有继承关系,那么实例化子类对象的初始化顺序为:父类静态成员的初始化父类静态代码块初始化子类静态成员的初始化子类静态代码块初始化父类成员的初始化父类初始化块父类构造器。

写写平时的技术与感想 2953

ARM 汇编指令:LSL(逻辑左移) 和 LSR(逻辑右移)

ARM 汇编中的 LSL(逻辑左移)和 LSR(逻辑右移)是基础移位指令,分别实现二进制位的左移和右移操作。LSL 低位补0,等效于乘以2^n;LSR 高位补0,等效于无符号除以2^n。这两个指令可以单独使用或与其他指令结合(如ADD、MOV等),利用ARM的"桶形移位器"硬件实现高效运算。关键特性包括:移位范围0-31(LSL)或1-32(LSR),可选更新标志位,以及与其他指令结合时的无额外开销优势。LSR与ASR(算术右移)的主要区别在于高位填充方式,分别适用于无符号和有符号数处理

guigenyi的专栏 1809

【转】JVM介绍

1. 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域。 JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字...

weixin_34200628的博客 427

RDD2022 数据格式转换与清洗

Rdd2022数据集,是关于道路损伤的数据集,与rdd2020相比增加了两万多张图片但是由于格式不能被yolo直接使用且其中有大量的图片没有符合要求的标注,特写此文章记录数据清洗与格式化的过程。

蓝胖子的博客 9942

MCP+A2A:从实验室到生产环境的落地之旅

本文通过实际项目中的落地案例,展示了 MCP+A2A 协议结合使用的强大功能和广泛适用性。同时,我们也探讨了开发者社区的贡献、与其他技术的融合,以及未来技术趋势的展望。希望本文能够帮助读者更好地理解如何将这一架构从实验室推向生产环境,推动 AI 技术的实际应用。

加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。 1492

JVM内存分配以及存储总结

最近看了一下JVM的内存分配,还是比较复杂的。这里做个总结,首先一个common sense就是操作系统会为每个java进程实例化一个jvm实例。jvm然后再来运行java程序,具体的过程就不多说了,简单来说就是核心classloader如bootstrap, extention, System对类的加载(一定是此顺序,jvm对类的加载采取的是代理委托方式,防止核心类被hack),找到对应的main

qingtiantianqing的博客 4482

YOLOv11改进策略【注意力机制篇】| SE、CBAM、ECA、CA、Swin Transformer等注意力机制全面解析与应用

本文详细介绍了五种主流的注意力机制及其在YOLOv11中的应用。通过合理的模块选择和位置部署,注意力机制能够显著提升目标检测性能。

QQ_778132974的博客 873

JAVA面向对象OOP→构造方法、this、访问修饰符、static、方法重载、JVM内存分配、GC垃圾回收、包、样例代码

构造方法(constructor):与类名同名,没有返回值 其初始化作用:一为属性分配内存空间、二为属性赋值 构造方法不能自己调用,只能通过new实例化对象调用 隐式构造方法:对象实例化时编译器会自动产生一个无参的构造方法,如果自己写了构造方法,系统就不再默认产生。 显示构造方法:初始化属性,带参是需要外部的参数确定初始化状态 this当前对象,当属性名和方法的参数同类型重名的时候优先使用属性名,为使参数名生效使用this.property表示当前属性 static 内存中只有一份,直接通过类名访问,属

实干、效率、武功、心法 214

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

jvm调音

jvm性能调优的目地:1)控制jvm的堆栈大小。比方当你的程序年轻代对象在某个时间段产生的比較多的时候,就须要控制年轻代的堆大小。同一时候还要控制总的JVM大小避免内存溢出2)控制GC的行为。GC是一个后台处理,可是它也是会消耗系统性能的,因此要依据执行程序的特点来更改GC行为。3)控制jvm线程的内存分配。假设是多线程程序,产生线程和线程执行所消耗的内存也是能够控制的。堆大小设置-...

aofan9566的博客 136

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

JAVA:JVM 创建对象时,堆会发生抢占吗?

本文探讨了Java多线程环境下对象创建时的内存分配问题。研究发现,JVM通过TLAB(Thread Local Allocation Buffer)机制有效避免了"堆抢占"现象。TLAB为每个线程分配独立的堆内存区域,使大多数对象分配无需加锁,只有当TLAB耗尽时才需要全局堆分配。通过对比实验发现,开启TLAB时对象分配效率显著高于关闭状态。文中还介绍了指针碰撞、Eden区并发分配等优化机制,建议在常规开发中保持TLAB开启以获得最佳性能。

木头 1572

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【DevOps】Java内存分配与JVM参数详解

JVM参数是用来控制JVM行为的一系列选项。这些参数可以影响内存分配、垃圾回收、线程行为等。-Xms:设置JVM堆的最小内存大小。-Xmx:设置JVM堆的最大内存大小。-Xmn:设置年轻代的大小。-Xss:设置线程栈的大小。:设置元空间初始大小。:设置元空间的最大大小。:启用G1垃圾回收器。:启用并行垃圾回收器。:启用CMS垃圾回收器。

TradingAgents-CN专栏 5714

【JVM学习总结系列】 JVM内存分配

首先谈谈对java语言的理解,java称为“半编译半解释”的语言。什么是编译?什么是解释?这个可以理解为机器是怎么看懂我们的代码。就好比我们(机器)去理解一篇外语文章(代码),如果先把文章翻译为中文,我们再读,就是编译型,如果是读一句,翻译一句,就是解释。那为什么java称为“半编译半解释”呢?是因为java编译器(javac)首先把java代码编译成class文件,然后在jvm中再把class文件的内容一点点解释给机器。

weixin_37838725的博客 1270

JVM的内存分配

JVM的内存分配与GC回收机制JVM内存分配元空间与方法区与永久代堆新生代老年代合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 JVM内存分配 JVM内存分为五部分:元空间(方法区)、堆、虚拟机栈、本地方法栈、程序计数器 元空间与方法区

weixin_51849480的博客 2583

JVM内存分配策略:对象创建与内存分配规则(含示例代码)

本文介绍了Java对象创建和内存分配的关键机制。JVM采用不同的内存分配策略:新对象优先在Eden区分配,大对象直接进入老年代,长期存活的对象经过多次GC后会晋升到老年代。对象创建过程包括类加载检查、内存分配、初始化零值、设置对象头和执行构造函数五个步骤。通过示例代码展示了对象在不同内存区域的分配情况,并指出理解这些机制有助于编写高效代码和解决内存问题。后续将深入探讨JVM垃圾回收机制,完善对内存模型的理解。

fykam的博客 2432

JVM对象创建和内存分配

new 对象会先去检查new的类是否被加载了。

qq_41184048的博客 1690

JVM内存分配策略

本篇内容来自深入理解java虚拟机_JVM高级特性和最佳实践 JVM内存分配策略 java的内存自动管理可以总结为自动分配和自动回收内存。 对象内存的分配主要是在堆上分配内存,对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程有限分配在TLAB上。少数情况可以直接分配在老年代中。 TLAB技术:JVM在内存新生代Eden Space中开辟了一小块线程私有的区域,称作TLAB(...

lidongxiu0714 3114

JVM内存分配(JDK8)

以一个Math类为列,从JVM运行时内存结构,到内存分配流程,最后内存分配参数的含义,串起整个流程。文章还待后续完善。

paopaodog的博客 1726

JVM之内存分配

用过哪些 JVM 调优工具?JVM 参数调优了解过吗?对象创建好后,怎么定位到这个对象?你知道指针碰撞和空闲列表分别是怎么去分配内存的吗?JVM 创建对象的时候怎么分配内存?JVM 是怎么创建对象的?了解内存分配的担保机制吗?你知道哪些内存分配策略?

2301_78145678的博客 1104

JVM内存划分、JVM内存分配机制、JVM垃圾回收机制

--------------------------------------------------- JVM内存管理分为两部分: 内存分配 内存回收 ------------------------------------------------------ 内存回收经常也被叫做垃圾回收。(附带资料:JVM面试题超链接、JVM性能调优和 参数说明) *很多人迷惑一个问题,既然J...

此处省略三千字 1万+
上一篇: JVM内存监控工具
下一篇: 帮你深入理解 JAVA 对象创建的过程
牧竹子
博客等级 码龄17年 572粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值