Java 溢出讲解(堆、栈、方法区)

news/2024/5/20 7:38:32 标签:

一、内存溢出

内存溢出:通常出现在某一块内存空间块耗尽的时候。OutOfMemory,简称OOM。

1、溢出

原因:大量对象占据了空间,而这些对象都持有强引用,导致无法回收,当对象大小之和大于由Xmx参数指定的空间大小时,溢出错误就自然而然地发生了。

如:

package com.krycai;

import java.util.ArrayList;

public class Test1 {

public static void main(String[] args) {

    ArrayList<Byte[]> list = new ArrayList<Byte[]>();

    for(int i=0; i<1024;i++) {

        list.add(new Byte[1024*1024]);

    }

}

}

2、直接内存溢出

直接内存:通过Java代码,获得一块外的内存空间,这块空间是直接向操作系统申请的。直接内存的申请速度一般要比内存慢,但其访问速度要快于内存。

 

3、过多线程导致OOM

由于每一个线程的开启都要占用系统内存,因此当线程数量太多时,也有可能导致OOM。由于线程的栈空间也是在外分配的,因此和直接内存非常相似,如果想让系统直接支持更多的线程,那么应该使用一个较小的空间。

方法:

(1)、尝试减少空间。 -Xmx512m

(2)、减少每个线程所占的内存空间,使用-Xss参数可以指定线程的栈空间。

-Xmx1g -Xss128k

4、永久区溢出

永久区:是存放类元数据的区域,如果一个系统定义太多的类型,name永久区是有可能溢出的。

解决策略:

(1)、增加MaxPermSize的值。

(2)、减少系统需要的类的数量。

(3)、使用ClassLoader合理地装载各个类,并定期进行回收。

二、String

1、特点

不变性: 对象一旦生成,则不能再对它进行改变。可以提高多线程访问(只读)的性能。

针对常量池的优化:当两个String对象拥有相同的值时,它们只引用常量池中的同一个拷贝。当一个字符串反复出现时,这个技术可以大幅度节省内存空间。

类的final定义:在系统中不可能有任何子类,这是对系统安全性的保护。

2、String的内存泄露

由于疏忽或者错误造成程序未能释放已经不再使用的内存的情况,它并不是说物理内存消失了,而是指由于不再使用的对象占据内存不被释放,而导致可用内存不断减少,最终由可能导致内存溢出

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

关于虚拟机栈和本地方法栈,在java虚拟机规范中描述了两种异常:

(1)、线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常

(2)、虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常

注:当栈空间无法继续分配时,到底是内存太小,还是已使用的栈空间太大,其本质上只是对同一件事情的两种描述而已。

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

方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这些区域的测试,基本的思路是运行时产生大量的类去填满方法区,直到溢出。

 

以上是简单的一些概念讲解,先有概念再去行动,针对性就比较强。

以上内容来源于 《实战Java虚拟机_JVM故障诊断与性能优化》《深入理解Java虚拟机 JVM高级特性与最佳实践》 的学习笔记,喜欢的点赞,谢谢。


http://www.niftyadmin.cn/n/1197374.html

相关文章

Open-E DSS V7 应用系列之四 构建软件RAID

续Open-E DSS V7 应用系列之三 Web管理简介一、RAID技术简介RAID&#xff08;Redundant Array of Independent Disks&#xff09;&#xff1a;独立冗余磁盘阵列&#xff0c;简称磁盘阵列。RAID是按照一定的形式和方案组织起来的存 储设备。它比单个存储设备在速度、稳定性和存储…

运行时数据区域

Java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。如下图所示&#xff1a; 1、程序计数器 程序计数器是一块较小的内存空间&#xff0c;它可以看作是当前线程所执行的字节码的行号指示器。 特点&#xff1a; A、字节码解释器工作时需要通过改变…

DataReader不奇怪,该出手时就出手!

夜里三点多&#xff0c;刚完成微博粉丝精灵V3.763的微博升级&#xff0c;上来看看&#xff0c;刚看到一篇文章&#xff1a;【原】关于使用DataReader的一个很奇怪的问题&#xff0c;不应该用DataReader&#xff1f; 于是准备花点时间解答下&#xff0c;顺便为这个月增添一篇文章…

linux安装-版本选择-终极决定

选用64位或32位的版本,注意看硬件: 内存大于4G的用64位, 小于4G的用32位 同时, 64位的版本在软件源, 软件的兼容性等问题. ----------------------------- 最终使用的是: red hat和centos系列的: fedora! 因为它的命令和配置都是跟服务器相同一致的, 这个既兼顾了桌面, 又兼顾…

类文件结构的简单描述

一、class类文件的结构 1、常量池 常量池&#xff1a;用于存放编译期生成的各种字面量和符号引用&#xff0c;这部分内容分将在类加载后进入方法区的运行时常量中存放。 字面量&#xff1a;比较接近java语言层面的常量概念&#xff0c;如文本字符串、声明为final的常量值等。…

CPU知识

CPU的指令集是什么 指令集是底层软件与硬件交互的语言。一台计算机的全部指令称为该计算机的指令集。 现在的常见的指令集有&#xff1a; MIPS指令集 ARM指令集 Intel x86指令集 指令集有两种形式&#xff0c;一种是人类可以编程书写的形式&#xff08;也就是平时所说的汇编语言…

虚拟机类加载机制的简单阐述

一、类加载机制 定义&#xff1a;虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#xff0c;最终形成可以被虚拟机直接使用的Java类型。 类加载周期&#xff1a;加载、验证、准备、解析、初始化、使用和卸载&#xff0c;其中验证…

Android的Activity生命周期

Android的Activity就相当于Windows Form中的Form&#xff0c;它的创建和销毁也是有一个生命周期的。主要经过这么7个阶段&#xff1a; 创建Activity&#xff1a;onCreate() 启动Activity&#xff1a;onStart() 恢复Activity&#xff1a;onResume() 暂停Activity&#xff1a;onP…