JVM的内存结构
步伐计数器
二进制字节码-->解释器-->机器码-->CPU
作用
记录下一条JVM指令的执行地址
特点
- 线程私有的(每个线程有自己的步伐计数器):java支持多线程运行,CPU给每个线程分配一个时间片,假如在时间片内没运行完,去执行另一个线程在执行该步伐。线程切换的过程中,将记录线程一应该执行的下一条代码
- 不会存在内存溢出
栈
捏造机参数
-Xss+内存大小
特点
先进后出(比方:手枪弹夹,羽毛球桶)
定义
- 捏造机栈:每个线程运行需要的内存空间
- 栈帧: 每个方法运行时需要的内存
- 每个线程由多个栈帧做成,对应着方法调用时占用的内存(方法内调用别的方法)
- 每个线程只能有一个活动栈帧,对应着当前正在执行的方法
执行完对应的方法后,栈帧出栈,将对应的内存开释掉
问题辨析
- 垃圾接纳是否涉及栈内存?
不需要,方法(栈帧)在执行后会被自动弹出栈
- 栈内存分配越大越好吗?
不是,栈内存越大,线程越少(机械内存固定10M,一个栈2M则可以运行5个线程;一个栈1M,则可运行10个线程)
- 方法内的局部变量是否安全?(多个线程对这个变量是共享的还是这个变量对每个线程是私有的)
不会,每个线程各有一个栈,各自的栈里各有一个栈帧存储x,互不干扰。
假如方法内局部变量没有逃离方法的作用访问,他是线程安全的
假如是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全
内存溢出
- 栈帧过多导致栈内存溢出(递归死循环)
- 栈帧过大(不太轻易出现)
线程诊断
- 用top定位哪个进程对cpu的占用过高
- ps H -eo pid,tid,%cpu|grep进程id(用ps命令进一步定位哪个线程引起cpu占用过多)
- jstack进程(可以根据线程id找到有问题的线程,进一步定位问题代码的源码行号)
- 案例二: 步伐运行很长时间没有结果(需要Linux操作系统)
本地方法栈
在调用本地方法是提供的内存空间(本地方法:不是由java代码编写的方法,Java代码的限制,底层的代码需要c/c++实现的本地方法。如:object类的clone()方法)
堆
捏造机参数
-Xmx+内存大小
Heap堆
通过new关键字,常见对象都会利用堆内存
特点
- 它是线程共享的,堆中对象都需要考虑线程安全性问题
- 有垃圾接纳机制
堆内存溢出
- String a = "hello";
- List<String> list = new ArrayList<>();
- while(true){
- list.add(a);
- a = a + a;
- }
复制代码 list:hello / hellohello / hellohellohello...
堆内存诊断
- jps工具:检察当前系统中有哪些java进程
- jmap工具:检察堆内存占用情况
- public class Main {
- public static void main(String[] args) throws InterruptedException {
- System.out.println("1....");
- Thread.sleep(30000);
- byte[] array = new byte[1024 * 1024 * 10];
- System.out.println("2....");
- Thread.sleep(30000);
- array = null;
- System.gc();
- System.out.println("3....");
- Thread.sleep(1000000L);
- }
- }
复制代码 运行以上代码打开控制台选择Terminl(命令行界面)
在“1...”打印出后输入jps
在“2...”打印出后输入jhsdb(看jdk,有的不需要) jmap -heap 45984(你运行的步伐前面的代号)
在“3...”打印出后输入jhsdb(看jdk,有的不需要) jmap -heap 45984(你运行的步伐前面的代号)
观察比较堆内存的利用情况
- jconsole工具:图形界面的多功能监测工具,可以一连监测
运行以上代码打开控制台选择Terminl(命令行界面)输入jconsole,回车会跳出Java监控和管理控制台,选择你运行的步伐连接-->不安全的;连接观察内存占用情况
案例
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |