Java内存模型常考题型

本文详细介绍了JVM的性能调优参数-Xms、-Xmx和-Xss的作用,以及它们如何影响Java程序的运行。同时,阐述了Java内存模型中堆和栈的区别,包括管理方式、空间大小、碎片问题和效率。此外,还解释了元空间、堆和线程独占部分在内存分配上的联系。最后,对比了JDK6和JDK6+中intern()方法的不同实现策略。

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

一、JVM三大性能调优参数-Xms -Xmx -Xss的含义

-Xss:规定了每个线程虚拟机栈(堆栈)的大小(一般情况下256k就足够了)此配置会影响进程中并发线程数的大小;
-Xms:堆的初始值即该进程创建出来时初始堆的大小,如果对象容量超过了初始值大小,会自动扩容,扩容的最大值就是-Xmx设置的值;
-Xmx:堆能达到的最大值;
一般情况下我们会将-Xms和-Xmx设置成一样大小,因为当Heap不够用,发生扩容时,会发生内存抖动,影响程序运行时的稳定性;

二、Java内存模型中堆和栈的区别

想要讲清楚区别,首先要先了解程序运行时的内存分配策略,总共有以下三种:

静态存储:编译时确定每个数据目标在运行时的存储空间需求,所以程序中不能存在可变数据型结构,也不允许有嵌套或递归的数据型结构出现,因为他们会导致编译程序时无法计算出存储空间;

栈式存储:数据取需求在编译时未知,运行时模块入口前确定,所以必须在运行时知道该模块的空间需求,才能分配内存,同样也是先进后出;

堆式存储:编译时或运行时模块入口都无法确定,动态分配;

接着再来了解一下堆和栈之间的联系:

我们知道创建好的对象实例或数组都放在堆中,想要使用堆中的对象实例或数组就需要在栈中定义一个变量,这个变量的取值就是想要使用的对象实例或数在堆中的首地址(也就是C语言中的指针),这样就能使用栈中的变量来使用堆中的对象实例或数组,当方法执行完时,栈中的变量就会被删除,而堆中的对象实例或数组是不会被删除的,只有当对象实例或数组没有被任何栈中变量引用时,才会被认为是垃圾,这时会由GC来将其回收,下图可以清晰的描述出栈是如何引用对中的数据:
在这里插入图片描述
所以在了解了联系之后,我们就能够总结出堆和栈两者的区别了,可以分为以下几种方式:

管理方式:栈自动释放,堆需要GC;
空间大小:栈比堆小;
碎片相关:栈产生的碎片远小于堆;
分配方式:栈支持静态和动态分配,而堆仅支持动态分配;
效率:栈的效率比堆高,但是堆的灵活性比栈好,有得必有失;

三、元空间、堆、线程独占部分间的联系-内存角度

下图为一段非常简单的代码:
在这里插入图片描述
当要执行该程序时,其中的变量都分别存储在什么位置呢?请看下图你就知道了:
类相关的信息都存在在了元空间中,包括System;
HelloWorld对象实例和name的对象实例都存在了堆中;
线程独占(也就是计数器和栈)存储了当前执行的行数,和对堆中两个对象实例引用的首地址;
在这里插入图片描述

四、不同JDK版本之间的intern()方法的区别——JDK6 VS JDK6+

String s = new String("a");
s.intern();

JDK6:当调用intern方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,将此字符串对象添加到常量池中,并且返回该字符串对象的引用。

JDK6+:当调用intern方法时,如果字符串常量池先前已创建出该字符串对象,则返回池中的该字符串的引用。否则,如果该字符串对象已经存在于Java堆中,则将堆中对此对象的引用添加到字符串常量池中,并且返回该引用;如果堆中不存在,则在池中创建该字符串并返回其引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值