当前位置:网站首页>JVM系列——栈与堆、方法区day1-2
JVM系列——栈与堆、方法区day1-2
2022-07-04 12:44:00 【简明编程】
JVM系列——栈与堆、方法区
栈
Java Virtual Machine Stacks (Java虚拟机栈)
线程运行时需要的内存空间,多个线程多个栈
栈的结构
栈中含有多个栈帧[Frame](链式调用时),栈帧就是每个方法运行时需要的内存
每个方法执行时都需要占用内存(参数、局部变量、返回值都需要分配内存)
当每个方法需要执行时,栈帧就会被压入栈内,直到方法执行完毕,栈帧就会出栈
注意!:每个线程只能有一个活动栈帧,对应正在执行的方法
先进后出
入栈
出栈
栈的演示
package stack;
public class StackTest {
public static void do1(int a) {
do2(a, 2);
}
public static int do2(int a, int b) {
return a * b;
}
public static void main(String[] args) {
do1(2);
}
}
将代码打断点进入调试查看
如何在IDEA中查看具体调试信息
栈结构查看
到这里我们看到整个栈结构是:main方法在最下面,然后是do1,最后是do2,接下来执行出栈
看到do2方法先消失了,说明最后执行的do2方法最先被压出栈中,若你查看旁边的变量窗口,可以看到变量的占用内存的情况
我们还可以看到在方法 :号后有一个数字
这个就是对应的程序的代码行(程序计数器作用!!!),根据这个地址信息就可以锁定执行顺序
栈的特性
- 栈不需要垃圾回收机制!
- 栈的内存并不是越大越好!在默认中栈的默认大小多为1024KB(windows系统依赖于虚拟空间大小),栈的内存越大线程数越少,运行效率反而变低
- 若方法内的局部变量没有脱离该方法的作用域则线程安全,否则线程不安全
栈溢出问题(StackOverflowError)
又称栈内存溢出
溢出的原因
1.栈帧过多导致,当方法进行递归调用时,没有设置正确的终止条件导致溢出),也可能时程序的循环依赖导致
2. 栈帧过大导致的内存溢出,我们可以设想这种场景,在进行递归调用时,我们的方法使用了可变长参数,导致参数变量多到将栈帧撑到超出了栈内存,但实际来说几乎见不到
IDEA自定义栈内存大小
选择编辑配置
选择修改选项–>添加VM选项
输入-Xss128k
就可以改为128k的大小了
线程运行诊断(linux)
在linux环境下,我们可以使用ps查看线程占用,top可以查看进程占用情况
ps H -eo pid,tid,%cpu | grep 进程id
通过使用jstack命令对进程进行诊断,列出线程情况,我们将线程id转换为16进制进行锁定即可知道具体线程导致的问题(nid)
jstack 进程id
建议使用jconsole
或jvisualvm
本地方法栈
Native Method Stacks
当本地方法接口进行调用时,本地方法栈为其提供内存空间
堆
Heap
我们通过使用new关键字创建的对象就会使用到堆内存
堆的特点
- 线程共享,需要考虑线程安全问题
- 堆中有垃圾共享机制
堆溢出问题(OutOfMemoryError)
当我们的程序不断产生新的变量,但是这些变量一直都在被使用的情况下就会产生,因为此时垃圾回收机制不生效,
IDEA自定义堆大小
和栈的方式一样,只要设置为:-Xmx堆大小
即可
堆内存诊断
1. jps
用于查看当前系统中有哪些Java进程
jps
2. jmap
用于查看堆的占用情况(某个时刻)
jmap -heap 进程号
3. jconsole
用于连续监测,含有GUI,是多功能监测工具!
jconsole
选择你要监视的进程
4.jvisualvm
堆转储dump:监测完整的堆具体信息
选择检查中的查找即可查看类信息
方法区(jdk1.8后移至本地内存)
逻辑上属于堆的一部分,不强制位置,是一种规范
方法区的内存结构方法区保存的信息包括:
- 类型信息:包括了JVM加载类型(类class、接口interface、枚举enum、注解annotation)的完整有效名称(包名+类名)、其直接父类的完整有效名称、类型的修饰符、其直接继承的接口列表。
- 域(成员变量)信息:类型的所有成员变量的相关信息以及成员变量的声明顺序。
- 方法信息:包括了类型的成员方法的名称、返回类型、参数列表、修饰符、字节码、操作数栈、局部变量表、异常表等。
- 静态变量:non-final的静态类变量和全局常量。区别在于全局常量在编译器给指定值,静态类变量在加载时准备阶段赋初值,初始化阶段再给指定值。
- JIT代码缓存:即时编译产生的代码缓存,将热点代码编译成与本地平台相关的机器码,并保存到内存。
- 运行时常量池:各种字面量和对类型、域和方法的符号引用。
同样方法区也会有内存溢出,而且同堆一样抛出OutOfMemoryError的异常(证明了逻辑定义)
由于StringTable在程序中会大量使用,若放置在方法区中时,StringTable的回收效率低下则会导致永久代的内存不足,所以从1.7起StringTable移动到堆中
常量池
编译后查看二进制字节码时使用到的一张表
虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
运行时常量池
常量池是*.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址
StringTable
是hashtable的结构,不能扩容
当我们程序运行时,常量池中的信息会进入运行时常量池,常量池中的符号并未变为Java字符串对象,直到程序执行到相对应的语句时才会进入StringTable中
特性
- 常量池中的字符串仅是符号,第一次用到时才变为对象利用串池的机制,来避免重复创建字符串对象
- 字符串变量拼接的原理是StringBuilder (jdk1.8)
- 字符串常量拼接的原理是编译期优化
- 可以使用intern方法,主动将串池中还没有的字符串对象放入串池中,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回(jdk1.8)
当字符串变量进行拼接时
采用new StringBuilder.append("str1").append("str2")....toString()
相当于直接new String("str")
(str = str1+str2…)
(原因:运行期间才能确定结果)
当字符串常量进行拼接时
直接合并出结果,并加入StringTable中(原因:编译期间就直接确定了结果)
StringTable的垃圾回收
设置VM Options : -Xmx8m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc
-Xmx8m : 设置堆为8mb
-XX:+PrintStringTableStatistics:设置打印StringTable统计信息
-Xlog:gc* :设置打印垃圾回收具体信息
//设置VM Options : -Xmx8m -XX:+PrintStringTableStatistics -Xlog:gc* -verbose:gc
//-Xmx8m : 设置堆为8mb
//-XX:+PrintStringTableStatistics:设置打印StringTable统计信息
//-Xlog:gc* :设置打印垃圾回收具体信息
public class StringTableGC {
public static void main(String[] args) {
int i = 0;
for (int j = 0; j < 100000; j++) {
//加入StringTable中
String.valueOf(j).intern();
i++;
}
System.out.println(i);
}
}
循环100次
循环10w次
这里可以看到触发了大量的垃圾回收
看完发现共有4次
StringTable性能调优
- 主要是调整hashTable中的桶个数(至少1009个)
-Xms500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=1010
- 采用字符串入池操作大量减少重复字符串
String.intern()
边栏推荐
- 再说rsync+inotify实现数据的实时备份
- Rsyslog配置及使用教程
- AI painting minimalist tutorial
- MySQL three-level distribution agent relationship storage
- Agile development / agile testing experience
- 使用 NSProxy 实现消息转发
- Alibaba cloud award winning experience: build a highly available system with polardb-x
- n++也不靠谱
- 诸神黄昏时代的对比学习
- 7、 Software package management
猜你喜欢
8 expansion sub packages! Recbole launches 2.0!
面试官:Redis 过期删除策略和内存淘汰策略有什么区别?
2022年中国移动阅读市场年度综合分析
阿里云有奖体验:用PolarDB-X搭建一个高可用系统
AI 绘画极简教程
Solution: how to delete the information of Jack in two tables with delete in one statement in Oracle
Concepts and theories related to distributed transactions
It is six orders of magnitude faster than the quantum chemical method. An adiabatic artificial neural network method based on adiabatic state can accelerate the simulation of dual nitrogen benzene der
ArcGis利用栅格处理工具进行影像裁剪
比量子化学方法快六个数量级,一种基于绝热状态的绝热人工神经网络方法,可加速对偶氮苯衍生物及此类分子的模拟
随机推荐
Is the outdoor LED screen waterproof?
PostgreSQL 9.1 飞升之路
Read the BGP agreement in 6 minutes.
一文掌握数仓中auto analyze的使用
Using scrcpy projection
众昂矿业:为保障萤石足量供应,开源节流势在必行
游戏启动后提示安装HMS Core,点击取消,未再次提示安装HMS Core(初始化失败返回907135003)
ASP.NET Core入门一
8个扩展子包!RecBole推出2.0!
SQL语言
[cloud native | kubernetes] in depth understanding of ingress (12)
DVWA range exercise 4
从0到1建设智能灰度数据体系:以vivo游戏中心为例
实时云交互如何助力教育行业发展
面试官:Redis 过期删除策略和内存淘汰策略有什么区别?
在 Apache 上配置 WebDAV 服务器
FS4056 800mA充电ic 国产快充电源ic
Meituan Ali's Application Practice on multimodal recall
求解:在oracle中如何用一条语句用delete删除两个表中jack的信息
Cann operator: using iterators to efficiently realize tensor data cutting and blocking processing