b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

jvm 栈内存 Java虚拟机管理内存溢出的问题及解决办法(上)

电脑杂谈  发布时间:2021-04-24 00:01:18  来源:网络整理

简介:

对于Java程序员,借助虚拟机的自动内存管理机制,无需自己释放内存,并且不容易出现内存泄漏和内存溢出问题。虚拟机的内存管理看起来非常好。 ,但是一旦出现内存溢出或内存泄漏,如果您不熟悉jvm虚拟机如何使用内存,则故障排除错误将是非常困难的任务。因此,在了解内存溢出之前,我们必须首先了解JVM内存模型。

JVM(Java虚拟机)是一种抽象计算模型。就像一台真正的机器一样,它具有自己的指令集和执行引擎,可以在运行时操纵内存区域。目的是为在其上构建的应用程序提供运行时环境。 JVM可以解释指令代码并与底层交互,包括操作系统平台和执行指令并管理资源的硬件体系结构。

JVM内存模型

根据JVM8规范,JVM运行时内存分为五个部分:虚拟机堆栈,堆,元空间,程序计数器和本地方法堆栈。内存中还有一部分叫做直接内存,它属于操作系统的本地内存,也可以直接操作。

好文推荐:从JVM模型谈十种内存溢出及解决方法

1.元空间(元空间)

元空间的性质类似于永久代的性质,并且两者都是JVM规范中方法区域的实现。但是,元空间和永久生成之间的最大区别是元空间不在虚拟机中,而是使用本地内存。

2.虚拟机堆栈(JVM堆栈)

每个线程都有一个专用堆栈,该专用堆栈是在创建线程时创建的。存储在堆栈中的是所谓的“堆栈框架”。每种方法都会创建一个堆栈框架。堆栈框架存储局部变量表(基本数据类型和对象引用),操作数堆栈,方法导出和其他信息。堆栈的大小可以是固定的,也可以动态扩展。

3.本机方法堆栈(本机方法堆栈)

类似于虚拟机堆栈,不同之处在于虚拟机堆栈执行java方法,而本地方法站执行本地方法。在虚拟机规范中,对于本地方法堆栈中的方法所使用的语言,用法和数据结构没有强制性规定,因此虚拟机可以自由实现。

4.程序计数器寄存器

程序计数器可以看作是当前线程执行的字节码行号的指示器。在任何给定时刻,处理器(用于多个内核的内核)将仅在一个线程中执行指令。因此,为了程切换后恢复到正确的执行位置,每个线程都需要一个独立的程序计数器。我们称这种类型的内存区域为“线程专用”内存。

5.堆内存(堆)

堆内存是由JVM的所有线程共享的部分,该部分在启动虚拟机时已经创建。所有对象和数组都分配在堆上。 GC可以回收这部分空间。当空间不可用时,将抛出OutOfMemoryError。堆是具有最大JVM内存占用量和最复杂管理的区域。它的唯一目的是存储对象实例:所有对象实例和数组都分配在该对上。在jdk 1. 8之后,将字符串常量池从永久代中剥离并存储在其中。

6.直接内存(直接内存)

在虚拟机运行时,直接内存不是数据区域的一部分,也不是Java虚拟机规范定义的内存区域。在JDK 1. 4中,新添加了NIO(新输入/输出)类,并引入了基于Channel和Buffer的I / O方法。它可以使用本机函数库直接分配堆内存,然后使用存储在Java堆中的DirectByteBuffer对象作为对此内存进行操作的引用。在某些情况下,这可以显着提高性能,因为它避免了在Java堆和本机堆之间来回复制数据。

十个内存溢出场景

当JVM运行时,类加载器(classLoader)首先需要加载所需类的字节码文件。加载后,由执行引擎执行。在执行期间,需要一个空间来存储数据(类似于CPU和主存储器)。该内存空间的分配和释放过程正是我们需要关注的运行时数据区域。当加载类加载器时,内存溢出情况开始。内存溢出分为两类:OutOfMemoryError和StackOverflowError。这是10种内存溢出情况,并通过示例代码说明内存溢出是如何发生的。

1. java堆内存溢出

出现时

java.lang.OutOfMemoryError:Java堆空间异常时,堆内存溢出。

1.问题描述

由1.设置的jvm内存太小,并且对象所需的内存太大。创建对象时分配空间时将抛出此异常。

2.流量/数据峰值,对于应用程序本身的处理有一定的限制,例如一定数量的用户或一定数量的数据。而且,当用户数量或数据量突然增加并超过预期的阈值时,在峰值停止之前的正常操作将停止并触发Java。

lang.OutOfMemoryError:Java堆空间错误

2.示例代码

编译以下代码,并在执行期间将jvm参数设置为-Xms20m -Xmx20m

好文推荐:从JVM模型谈十种内存溢出及解决方法

在上面的示例中,如果仅为一个请求分配5m的内存,则请求量很小并且垃圾回收正常,不会有任何错误,但是一旦并发出现,最大内存值将为超过,将引发内存溢出。

3.解决方案

首先,如果代码没有问题,则可以适当地调整两个jvm参数-Xms和-Xmx,并使用压力测试将这两个参数调整为最佳值。

第二,尝试避免使用大型对象的应用程序,例如文件上载和从中获取大量数据的应用程序,这是需要避免的。尝试尽可能地阻止或批处理,以帮助系统正常稳定地执行。

最后,尝试尽快提高请求的执行速度。垃圾收集越早越好。否则,当有大量并发请求进入时,将无法为新请求分配内存,这很容易导致系统雪崩。

2. java堆内存泄漏

1.问题描述

在Java中,内存泄漏是指某些对象不再被应用程序使用但无法被垃圾回收识别的情况。因此,这些未使用的对象仍然无限期地存在于Java堆空间中。累积最终将触发Java。 lang.OutOfMemoryError。

2.示例代码

好文推荐:从JVM模型谈十种内存溢出及解决方法

执行上述代码时,可以预期它将永久运行而不会出现任何问题。假设纯缓存解决方案仅将基础映射扩展到10,000个元素,而不是所有键都已经在HashMap中。但是,实际上,将继续添加元素,因为键类不会覆盖其equals()方法。

随着时间的流逝,随着泄漏代码的连续使用,“缓存”的结果最终将消耗大量Java堆空间。当泄漏的内存填满堆区域中的所有可用内存时,垃圾回收无法清除它,即java.lang.OutOfMemoryError。

3.解决方案

相应的解决方案相对简单:只需重写equals方法:

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.垃圾回收超时内存溢出

1、问题描述

当应用程序所有可用内存都用完时,GC开销限制超过了错误,并且GC多次清除失败,然后将其触发

java.lang.OutOfMemoryError。当JVM花大量时间执行GC时,效果很小,并且一旦整个GC进程超过了限制,就会触发错误(默认的JVM配置GC时间超过98%,并且恢复了堆内存)小于2%)。

2.示例代码

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.解决方案

为减少对象的生命周期,请尝试尽快收集垃圾。

4.元空间内存溢出

1.问题描述

元空间溢出,系统将丢弃

java.lang.OutOfMemoryError:元空间。出现此异常问题的原因是系统具有大量代码或引用了许多第三方程序包,或者通过诸如动态代码生成,类加载等方法,导致元空间的内存占用量很大。

2.示例代码

以下是通过在循环中动态生成类来模拟元空间的内存溢出。

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.如何解决元空间的内存溢出?

默认情况下,元空间的大小仅受本地内存限制。但是对于整机的性能而言,仍然有必要尽可能地设置此项以避免整机的服务停机。

1)优化参数配置,以避免影响其他JVM进程

-XX:MetaspaceSize,初始空间大小。当达到此值时,将触发垃圾回收以进行类型卸载。同时,GC将调整该值:如果释放了大量空间,则应适当减小该值;如果空间较小,则当空间不超过MaxMetaspaceSize时,适当增加该值。

-XX:MaxMetaspaceSize,最大空间,默认情况下没有限制。

除了上面两个指定的大小选项外,还有两个与GC相关的属性:

-XX:MinMetaspaceFreeRatio,在GC之后,是最小的Metaspace剩余空间容量的百分比,从而减少了由分配的空间引起的垃圾回收。

-XX:MaxMetaspaceFreeRatio,在GC之后,是最大的Metaspace的剩余空间容量的百分比,从而减少了由自由空间引起的垃圾收集。

2)仔细引用第三方程序包

对于第三方软件包,您必须仔细选择并删除不需要的软件包。这不仅有助于提高编译和打包的速度,而且还有助于提高远程部署的速度。

3)关注动态生成的类的框架

对于使用大量动态生成类的框架,有必要进行压力测试以验证动态生成类是否超出内存要求并引发异常。

5.直接内存内存溢出

1.问题描述

在ByteBuffer中使用allocateDirect()时使用。许多javaNIO(如netty)框架都被封装为其他方法,并且会引发此问题

java.lang.OutOfMemoryError:直接缓冲存储器异常。

如果直接或间接使用ByteBuffer中的allocateDirect方法,当您不清除时,也会发生类似的问题。

2.示例代码

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.解决方案

如果经常执行类似的操作,则可以考虑设置参数:-XX:MaxDirectMemorySize,并及时清除内存。

6.堆栈内存溢出

1.问题描述

当线程执行Java方法时,JVM将创建一个新的堆栈框架并将其推入堆栈的顶部。此时,新的堆栈帧将成为当前的堆栈帧。执行该方法时,堆栈帧用于存储参数,局部变量,中间指令和其他数据。

当方法递归调用自身时,新方法生成的数据(也可以理解为新的堆栈框架)将被推入堆栈的顶部,并且每次该方法自身调用时,它都会复制当前方法的数据数据被压入堆栈。因此,递归调用的每一层都需要创建一个新的堆栈框架。其结果是递归调用将占用越来越多的堆栈内存。如果递归地调用自己一百万次,则将生成一百万个堆栈帧。这将导致堆栈溢出。

2.示例代码

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.解决方案

如果程序中有递归调用,则在发生堆栈溢出时,可以增加-Xss的大小来解决堆栈内存溢出的问题。递归调用可防止形成无限循环,否则将发生堆栈内存溢出。

7.创建本地线程内存溢出

1.问题描述

线程基本上只占用堆以外的内存区域,这意味着该错误表明除了堆以外的区域之外,无法为线程分配内存区域。这要么是内存本身不足,要么是堆空间设置太大,导致剩余内存不足,并且由于线程本身占用了内存,所以还不够。

好文推荐:从JVM模型谈十种内存溢出及解决方法

jvm 栈内存_jvm设置栈内存大小_jvm有几个栈

3.解决方案

首先检查操作系统是否对线程数有限制,并且不能使用Shell创建线程。如果出现问题,则需要调整系统可以支持的最大文件数。

在日常开发中,请尝试确保最大数量的线程是可控制的,并且不要随意使用线程池。它不能无限制地继续增长。

8.超出交换区内存溢出

1.问题描述

在Java应用程序的启动过程中,可以使用-Xmx和其他类似的启动参数来限制指定的所需内存。当JVM请求的总内存大于可用的物理内存时,操作系统开始将内容从内存转换为硬盘。

通常来说,JVM将抛出“交换空间不足”错误,这意味着当应用程序无法从JVM本机堆分配内存并且本机堆即将用尽时,错误消息将包含分配失败(以字节为单位))以及请求失败的原因。

2.解决方案

增加系统交换区的大小。我个人认为,如果使用交换区域,性能将会大大降低。不建议使用此方法。生产环境应尽量避免最大内存超过系统的物理内存。其次,删除系统交换区域,仅使用系统内存来确保应用程序的性能。

9.数组溢出内存溢出

1.问题描述

有时您会遇到这种内存溢出说明,请求的数组大小超出了VM限制。一般来说,Java对应用程序可以分配的数组的最大大小有限制,但是在不同的平台上,限制是不同的。但是它通常在100到21亿之间。当请求的数组大小超过VM限制时,将发生错误,这意味着应用程序正在尝试分配比Java虚拟机可以支持的更大的数组。在为阵列分配内存之前,JVM将执行特定于平台的检查:分配的数据结构在该平台上是否可寻址。

2.示例代码

以下是数组超出最大限制的代码。

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.解决方案

因此,数组的长度必须在平台允许的长度内。但是,此错误通常很少见,主要是因为Java数组的索引为int类型。 Java中最大的正整数是2 ^ 31-1 = 2,147,483,647。特定于平台的限制可能非常接近此数字,例如:在我的环境(64位macOS中,运行Jdk 1. 8)可以将数组的长度初始化为高达2,147,483,645(Integer.MAX_VALUE- 2)。将长度增加1即可达到nteger.MAX_VALUE-1,这将导致OutOfMemoryError。

1 0.系统消除了进程内存溢出

1.问题概述

在描述问题之前,让我们熟悉操作系统的知识:操作系统基于进程的概念构建,并且这些进程在内核中运行。其中一个非常特殊的过程称为“ Memory Killer(内存不足杀手)”。当内核检测到系统内存不足时,将激活OOM杀手,检查谁当前占用的内存最多,然后杀死该进程。

常规内存不足:当消耗了可用的虚拟虚拟内存(包括交换空间)以使整个操作系统处于危险之中时,将触发终止进程或牺牲子错误。在这种情况下,OOM Killer将选择“恶意进程”并将其杀死。

2.示例代码

好文推荐:从JVM模型谈十种内存溢出及解决方法

3.解决方案

尽管增加交换空间可以缓解异常的Java堆空间,但建议最好的解决方案是升级系统内存,以便Java应用程序具有足够的可用内存,这样就不会发生此问题。

摘要

通过以上10种内存溢出情况,每个人在实际遇到问题时都会知道如何解决该问题,并记住实际编码:

1.应当仔细介绍第三方jar软件包,并且必须坚决删除无用的jar软件包,以提高编译速度和系统内存使用率。

2.对于大型对象或大量内存应用程序,应进行优化,并应将大型对象分段处理,以提高处理性能并缩短对象生命周期。

3.尝试尽可能固定线程数,以确保线程所占用的内存是可控制的。同时,当需要大量线程时,应优化操作系统的最大打开连接数。

4.对于递归调用,还应控制递归级别,不要太高,以超过堆栈的深度。

5.分配给堆栈的内存越大越好,因为堆栈内存越大,线程越多且堆剩下的空间越少,就很容易引发OOM。 JVM的默认参数通常没有问题(包括递归)。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-370440-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...