JAVA虚拟机-第2章 Java自动内存管理-异常实践

Java堆溢出

堆的参数设置:将堆的最小值-Xms参数与最大值-Xmx参数设置
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

public class HeapOOM {static class OOMObject {}public static void main(String[] args) {List<OOMObject> list = new ArrayList<OOMObject>();while (true) {list.add(new OOMObject());}}
}

在这里插入图片描述
出现Java堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟随进一步提示“Java heap space”。
因为List溢出啦 它存在堆区
解决方法:
第一步首先应确认内存中导致OOM的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)
内存泄漏:
内存溢出:

虚拟机栈和本地方法栈溢出

栈容量只能由-Xss参数来设定
关于虚拟机栈和本地方法栈,在《Java虚拟机规范》中描述了两种异常
1)如果线程请求的栈深度(栈容量 栈帧大小)大于虚拟机所允许的最大深度,将抛出StackOverflowError异常。
2)如果虚拟机的栈内存允许动态扩展,当扩展栈容量无法申请到足够的内存时,将抛出
OutOfMemoryError异常。
一般HotSpot不会产生OutOfMemoryError 因为其不允许动态扩展 只能加高深度达到栈溢出
·使用-Xss参数减少栈内存容量。
结果:抛出StackOverflowError异常,异常出现时输出的堆栈深度相应缩小。
代码

public class JavaVMSTackSOF {/***VM Options:-Xss128k*/private int stackLength = 1;public void stackLeak() {stackLength++;stackLeak();}public static void main(String[] args) throws Throwable {JavaVMSTackSOF oom = new JavaVMSTackSOF();try {oom.stackLeak();} catch (Throwable e) {System.out.println("stack length:" + oom.stackLength);throw e;}}
}

结果:
在这里插入图片描述
·定义了大量的本地变量,增大此方法帧中本地变量表的长度。
结果:抛出StackOverflowError异常,异常出现时输出的堆栈深度相应缩小。
代码:

public class JavaVMSTackSOF {private static int stackLength = 0;public static void test() {long unused1, unused2, unused3, unused4, unused5,unused6, unused7, unused8, unused9, unused10,unused11, unused12, unused13, unused14, unused15,unused16, unused17, unused18, unused19, unused20,unused21, unused22, unused23, unused24, unused25,unused26, unused27, unused28, unused29, unused30,unused31, unused32, unused33, unused34, unused35,unused36, unused37, unused38, unused39, unused40,unused41, unused42, unused43, unused44, unused45,unused46, unused47, unused48, unused49, unused50,unused51, unused52, unused53, unused54, unused55,unused56, unused57, unused58, unused59, unused60,unused61, unused62, unused63, unused64, unused65,unused66, unused67, unused68, unused69, unused70,unused71, unused72, unused73, unused74, unused75,unused76, unused77, unused78, unused79, unused80,unused81, unused82, unused83, unused84, unused85,unused86, unused87, unused88, unused89, unused90,unused91, unused92, unused93, unused94, unused95,unused96, unused97, unused98, unused99, unused100;stackLength ++;test();unused1 = unused2 = unused3 = unused4 = unused5 =unused6 = unused7 = unused8 = unused9 = unused10 =unused11 = unused12 = unused13 = unused14 = unused15 =unused16 = unused17 = unused18 = unused19 = unused20 =unused21 = unused22 = unused23 = unused24 = unused25 =unused26 = unused27 = unused28 = unused29 = unused30 =unused31 = unused32 = unused33 = unused34 = unused35 =unused36 = unused37 = unused38 = unused39 = unused40 =unused41 = unused42 = unused43 = unused44 = unused45 =unused46 = unused47 = unused48 = unused49 = unused50 =unused51 = unused52 = unused53 = unused54 = unused55 =unused56 = unused57 = unused58 = unused59 = unused60 =unused61 = unused62 = unused63 = unused64 = unused65 =unused66 = unused67 = unused68 = unused69 = unused70 =unused71 = unused72 = unused73 = unused74 = unused75 =unused76 = unused77 = unused78 = unused79 = unused80 =unused81 = unused82 = unused83 = unused84 = unused85 =unused86 = unused87 = unused88 = unused89 = unused90 =unused91 = unused92 = unused93 = unused94 = unused95 =unused96 = unused97 = unused98 = unused99 = unused100 = 0;}public static void main(String[] args) {try {test();}catch (Error e){System.out.println("stack length:" + stackLength);throw e;}}
}

在这里插入图片描述
如果测试时不限于单线程,通过不断建立线程的方式,在HotSpot上也是可以产生内存溢出异常
的,具体如代码清单2-6所示。但是这样产生的内存溢出异常和栈空间是否足够并不存在任何直接的关系,主要取决于操作系统本身的内存使用状态。

方法区和运行时常量池溢出

由于运行时常量池是方法区的一部分,所以这两个区域的溢出测试可以放到一起进行。
JDK6
String::intern()是一个本地方法,它的作用是如果字符串常量池中已经包含一个等于此String对象的
字符串,则返回代表池中这个字符串的String对象的引用;否则,会将此String对象包含的字符串添加
到常量池中,并且返回此String对象的引用。但自JDK 7起,原本存放在永久代的字符串常量池被移至Java堆之中
JDK7
方法区的主要职责是用于存放类型的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这部分区域的测试,基本的思路是运行时产生大量的类去填满方法区,直到溢出为止。虽然直接使用Java SE API也可以动态产生类(如反射时的GeneratedConstructorAccessor和动态代理等),但在本次实验中操作起来比较麻烦。借助了CGLib[3]直接操作字节码运行时生成了大量的动态类。很多运行于Java虚拟机上的动态语言(例如Groovy等)通常都会持续创建新类型来支撑语
言的动态性,随着这类动态语言的流行,溢出场景也越来越容易遇到
JDK8
在JDK 8以后,永久代便完全退出了历史舞台,元空间作为其替代者登场。在默认设置下,前面
列举的那些正常的动态创建新类型的测试用例已经很难再迫使虚拟机产生方法区的溢出异常了。不过
为了让使用者有预防实际应用里出现类似于代码清单2-9那样的破坏性的操作,HotSpot还是提供了一
些参数作为元空间的防御措施,主要包括:
·-XX:MaxMetaspaceSize:设置元空间最大值,默认是-1,即不限制,或者说只受限于本地内存
大小。
·-XX:MetaspaceSize:指定元空间的初始空间大小,以字节为单位,达到该值就会触发垃圾收集
进行类型卸载,同时收集器会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放
了很少的空间,那么在不超过-XX:MaxMetaspaceSize(如果设置了的话)的情况下,适当提高该
值。
·-XX:MinMetaspaceFreeRatio:作用是在垃圾收集之后控制最小的元空间剩余容量的百分比,可
减少因为元空间不足导致的垃圾收集的频率。类似的还有-XX:Max-MetaspaceFreeRatio,用于控制最大的元空间剩余容量的百分比。

本机直接内存溢出

直接内存(Direct Memory)的容量大小可通过-XX:MaxDirectMemorySize参数来指定,如果不
去指定,则默认与Java堆最大值(由-Xmx指定)一致。代码越过了DirectByteBuffer类直接通过反射获取Unsafe实例进行内存分配(Unsafe类的getUnsafe()方法指定只有引导类加载器才会返回实例,体现了设计者希望只有虚拟机标准类库里面的类才能使用Unsafe的功能,在JDK 10时才将Unsafe的部分功能通过VarHandle开放给外部使用),因为虽然使用DirectByteBuffer分配内存也会抛出内存溢出异常,但它抛出异常时并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配就会在代码里手动抛出溢出异常,真正申请分配内存的方法是Unsafe::allocateMemory()。

//VM-Options -Xmx20M -XX:MaxDirectMemorySize=10M
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
//反射 
//反射是Java中的一个功能,它允许程序在运行时访问和修改它自身的结构和行为。这意味着你的程序可以在运行时分析和操作类、接口、字段和方法。//使用Java的反射API,程序能够://创建任何类的对象。
//获取类的所有构造方法、字段、方法和注解。
//调用任何类的任何方法。
//改变任何类的字段值,即使它们被标记为私有
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}

结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/178401.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JTS: 13 Polygonizer 多线合成面

这里写目录标题 版本代码 版本 org.locationtech.jts:jts-core:1.19.0 链接: github 代码 线段 生成之后的面 public class GeometryPolygonization {private static final GeometryFactory geometryFactory new GeometryFactory();private static final Logger LOGGER …

陪诊系统|挂号陪护搭建二开陪诊师入驻就医小程序

我们的陪诊小程序拥有丰富多样的功能&#xff0c;旨在最大程度满足现代人的需求。首先&#xff0c;我们采用了智能排队系统&#xff0c;通过扫描二维码获取排号信息&#xff0c;让您从繁琐的排队过程中解放出来。其次&#xff0c;我们提供了多种支付方式&#xff0c;不仅可以实…

管理类联考——数学——汇总篇——知识点突破——代数——函数、方程——记忆

文章目录 考点记忆/考点汇总——按大纲 整体局部 本篇思路&#xff1a;根据各方的资料&#xff0c;比如名师的资料&#xff0c;按大纲或者其他方式&#xff0c;收集/汇总考点&#xff0c;即需记忆点&#xff0c;在通过整体的记忆法&#xff0c;比如整体信息很多&#xff0c;通常…

python线程(进程子单位)

进程是由CPU给分配的执行单元&#xff0c;比较消耗空间和内存 创建、使用线程 import threading# 进程 # 线程 from time import sleepdef download():list1 ["girl.png", "boy.png", "child.png"]for l in list1:print(l)sleep(1.5)print(&qu…

变量的作用域

在javascript中&#xff0c;var定义的变量实际是有作用域的。 1 假设在函数体内声明&#xff0c;但在函数体外不可以使用 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </…

Java实验一编程环境使用

1&#xff0e;String类的常用方法&#xff08;StringExample.java&#xff09; package step1;public class StringExample {public static void main(String args[]) {String s1 new String("you are a student");String s2 new String("how are you")…

Lodash 真的死了吗?Lodash 5 在哪里?

与一些传言相反&#xff0c;Lodash依然活跃&#xff0c;并正在迈向Lodash 5的发布&#xff01; Lodash 是那些为 JavaScript 提供便利功能的实用程序库之一&#xff0c;它使编程变得更加轻松。许多开发者使用它来简化对象和数组的处理。 它也是一个像 Moment.js那样被捕获得措手…

038-第三代软件开发-简易视频播放器-自定义Slider (二)

第三代软件开发-简易视频播放器-自定义Slider (二) 文章目录 第三代软件开发-简易视频播放器-自定义Slider (二)项目介绍简易视频播放器自定义Slider (二)横向纵向 关键字&#xff1a; Qt、 Qml、 关键字3、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&…

【UE】从UI中拖拽生成物体

目录 效果 步骤 一、准备工作 二、创建UI 三、创建Actor 四、拖拽生成Actor的逻辑 效果 步骤 一、准备工作 1. 首先新建一个第三人称模板工程 2. 新建一个游戏模式基础&#xff0c;这里命名为“BP_UIGameMode” 在世界场景设置中设置游戏模式覆盖为“BP_UIGameMode”…

Vue中切换tab路由,提示this.$confirm确定和取消执行不同的逻辑

beforeRouteLeave (to, from, next) { // 离开页面 if (this.editFlag true) { this.$confirm(页面尚未保存&#xff0c;确认离开吗?, 提示, { distinguishCancelAndClose: true, // 区分取消和关闭 confirmButtonText: 确定, cancelButtonText: 取消, type: info }).then(()…

RT-Thread 9. VS2012下仿真RT-Thread 和LVGL

1. 在ENV中添加组件 2. 下载组件 3. 生成代码 4. 打开代码 双击project.vcxproj 编译 5. 运行

Linux | 如何保持 SSH 会话处于活动状态

在远程服务器管理和安全数据传输中&#xff0c;SSH&#xff08;Secure Shell&#xff09;是不可或缺的工具。然而&#xff0c;它的便利性和安全性有时会因常见的问题而受到损害&#xff1a;冻结 SSH 会话。 此外&#xff0c;session 的突然中断可能会导致工作丢失、项目延迟和无…

深度学习_1 介绍;安装环境

深度学习 学习自李沐老师的课程。笔记主要以总结老师所讲解的内容以及我个人的想法为主&#xff0c;侵删&#xff01; 课程链接&#xff1a;课程安排 - 动手学深度学习课程 (d2l.ai) 介绍 AI地图&#xff1a; 我们以前写的非 AI 类程序基本都是人自己去想会遇到什么样的问题…

基于transformer的解码decode目标检测框架(修改DETR源码)

提示:transformer结构的目标检测解码器,包含loss计算,附有源码 文章目录 前言一、main函数代码解读1、整体结构认识2、main函数代码解读3、源码链接二、decode模块代码解读1、decoded的TransformerDec模块代码解读2、decoded的TransformerDecoder模块代码解读3、decoded的De…

Ubuntu 20.04设置虚拟内存 (交换内存swap)解决内存不足

数据库服务器程序在运行起来之后&#xff0c;系统内存不足。 在系统监控中发现&#xff0c;当数据库服务程序启动后&#xff0c;占用了大量内存空间&#xff0c;导致系统的剩余的内存往往只有几十MB。 在ubuntu系统中&#xff0c;swap空间就是虚拟内存&#xff0c;所以考虑在磁…

【kubernetes】k8s对象☞pod

文章目录 1、什么是pod2、pod的使用2.1 用于管理pod的工作负载资源2.2 pod怎样管理多个容器2.3 pod 操作系统2.4 pod和控制器2.5 pod模板 3、pod的更新与替换3.1 资源共享和通信3.2 pod中的存储3.3 pod联网 4、容器的特权模式4.1 linux 特权容器4.2 windows特权容器 5、静态pod…

ES 8.x新特性一览(完整版)

一、看点 在 2022 年 2 月 11 日&#xff0c;Elasticsearch&#xff08;ES&#xff09;正式发布了 8.0 版本&#xff0c;而截止到 2023 年 10 月&#xff0c;历经一年半时间&#xff0c;ES官方已经连续发布了多个版本&#xff0c;最新版本为 8.10.4。这一系列的更新引入了众多引…

极智开发 | H100服务器的庐山真面目

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文分享一下 H100服务器的庐山真面目。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq H100 是英伟达最强显卡,当然其实也…

【GitLab、GitLab Runner、Docker】GitLab CI/CD 应用

安装Gitlab开源版 官方文档-安装Gitlab 使用Docker安装 sudo docker run --detach \--hostname gitlab.example.com \--env GITLAB_OMNIBUS_CONFIG"external_url http://${ip}:9999/; gitlab_rails[gitlab_shell_ssh_port] 8822;" \--publish 443:443 --publish 99…

基于深度学习的人脸专注度检测计算系统 - opencv python cnn 计算机竞赛

文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的人脸专注度…