虚拟机栈内存溢出问题虚拟机栈在默认情况下为1024K,正常情况下不会溢出,但如果出现异常可能导致溢出
首先我们介绍一个改变虚拟机栈的方法:
// 在配置运行环境的Environment variables中进行配置(如下修改为256k)-Xss256k
然后我们介绍两种溢出情况:
- 栈帧过多
// 正常情况下我们的栈帧(方法)就算再多也不会导致内存溢出,但是如果我们发生了无限递归异常呢?// 我们在这个方法中递归调用本身,就会导致不断有栈帧加入到虚拟机栈中,最终导致虚拟机栈内存溢出package cn.itcast.jvm.t1.stack;/** * 演示栈内存溢出 java.lang.StackOverflowError * -Xss256k */public class Demo1_2 {private static int count;public static void main(String[] args) {try {method1();} catch (Throwable e) {e.printStackTrace();System.out.println(count);}}private static void method1() {count++;method1();}}
- 栈帧过大
/*我们仅仅是来解释这个溢出想法但实际上我们的默认虚拟机栈大小为1M,是不可能出现栈帧过大的情况的~*/
虚拟机线程实际问题运行判断我们会给出两个实际案例来进行讲解:- CPU占用过多
// 我们的项目通常都会运行在Linux服务器上,所以我们下面通过Linux来介绍方法// 首先通过top定位哪个进程对cpu的占用过高top // 然后我们通过ps命令进一步查看哪个线程引起cpu占用率过高ps H -eo pid,tid,%cpu | grep 进程id// 最后我们查看线程具体问题jstack 进程id// 最后我们到我们的项目代码中进行检查会发现问题(可能是死循环之类的)package cn.itcast.jvm.t1.stack;/** * 演示 cpu 占用过高 */public class Demo1_16 {public static void main(String[] args) {new Thread(null, () -> {System.out.println("1...");while(true) {}}, "thread1").start();new Thread(null, () -> {System.out.println("2...");try {Thread.sleep(1000000L);} catch (InterruptedException e) {e.printStackTrace();}}, "thread2").start();new Thread(null, () -> {System.out.println("3...");try {Thread.sleep(1000000L);} catch (InterruptedException e) {e.printStackTrace();}}, "thread3").start();}}
- 程序运行过久没有结果
/*我们采用之前相同的方法来进行判断,一般运行过久没有结果都是发生死锁问题*/package cn.itcast.jvm.t1.stack;/** * 演示线程死锁 */class A{};class B{};public class Demo1_3 {static A a = new A();static B b = new B();public static void main(String[] args) throws InterruptedException {new Thread(()->{synchronized (a) {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (b) {System.out.println("我获得了 a 和 b");}}}).start();Thread.sleep(1000);new Thread(()->{synchronized (b) {synchronized (a) {System.out.println("我获得了 a 和 b");}}}).start();}}
本地方法栈这小节我们来介绍JVM内存结构中的本地方法栈本地方法简介首先我们先来简单介绍一下本地方法:
- JVM属于Java层次的东西,是无法通过Java与底层进行交互
- 这时我们就需要一些采用C,C++语言的方法来与底层进行交互,这种方法就被称为本地方法
- 本地方法大多设置为接口,其返回值类型为native
- 我们常见的本地方法包括有Object中的clone方法,hashCode方法,wait方法等
- 本地方法栈就是一个存储本地方法的栈
- 其原理与虚拟机栈完全相同,只不过里面的栈帧变为了本地方法而已
堆简介首先我们需要先理解什么是堆:
- 堆的本体通常可以被看做一棵完全二叉树的数组
经验总结扩展阅读
- 【lwip】08-ARP协议一图笔记及源码实现
- 用一台笔记本电脑如何赚钱(笔记本电脑赚钱的办法)
- 小米笔记本Pro15增强版评测_小米笔记本Pro15增强版评测表现
- 笔记本电脑CF中烟雾头怎么调(win10cf新版本烟雾保护头怎么调)
- 笔记本电脑配置高低怎么区分(笔记本电脑看什么配置判断好坏)
- 四 【单片机入门】应用层软件开发的单片机学习之路-----ESP32开发板PWM控制电机以及中断的使用
- pytorch、paddlepaddle等环境搭建 深度学习环境搭建常用网址、conda/pip命令行整理
- 三十九 Java开发学习----SpringBoot整合mybatis
- 2023年圣诞节学习运有所提升的星座智慧多多成绩提升
- 电脑开不了机怎么办简单方法(笔记本电脑开不了机)