1 JVM架构
线程私有内存:程序计数器,Java虚拟机栈,本地方法栈
线程共享内存:Java堆,方法区
引用
程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器。如果线程执行的是一个java方法,这个计算器记录的是正在持行的虚拟机字节码指令的地址;如果执行的是Native方法,这个计数器则为空。此区域是java虚拟器规范中唯一没有定义任何OutOfMemoryError情况的区域
引用
Java虚拟机栈:它是描述java方法执行的内存模型:每个方法被执行的时候都会创建一个stack frame用于储存局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈道出栈的过程。
如果线程所请求的栈深度大于虚拟机所永许的深度,将抛出StackOverflowError,如果虚拟机栈可以动态扩展,当扩展时无法申请足够的内存时会抛出OutOfMemoryError。
引用
本地方法栈:与java虚拟机栈作用类似,不过他是位执行Native方法服务。本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError
引用
Java堆: 它是虚拟机管理的内存中最大的一块。它是被所有线程共享的一块区域,是虚拟机创建的。它是存放对象实例,几乎所有对象实例都在堆上分配。它是垃圾回收器管理的主要区域。可以进一步分为Eden空间,from survivor控件爱你,to survivor空间等,可以通过-Xmx 和 -Xms 控制堆的大小,当缺少内存时出现OutOfMemoryError
引用
方法区:它和java堆一样,是各个线程共享的内存区域,它用于存储以被虚拟器加载的类信息/常量/静态变量/即时编译器编译后的代码等数据。如果它无法满足内存分配,将抛出OutOfMemoryError异常。
运行时常量池:它是方法区的一部分,Class文件中除啦有类的版本,字段,方法,接口等描述性信息外,还有一个是常量池(Constant Pool Table),用于存放编译器生成的各种字面量和符号引用,这部分内容会在类加载后存放到方法去的运行时常量池中。当缺少内存时出现OutOfMemoryError
2 基于sun jvm 实战OutOfMemoryError异常情况和分析过程
堆内存错误分析
import java.util.ArrayList;
import java.util.List;
/**
*VM Arguments: -verbose:gc -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
*/
public class HeapOOM {
static class OOMObject{}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while(true) {
list.add(new OOMObject());
}
}
}
添加eclipse运行参数 -verbose:gc -Xms20m -Xmx20m
参数含义
-verbose:gc | 显示gc过程 |
-Xms | 堆的最小动态内存 |
-Xmx | 堆的最大动态内存 |
-XX:+HeapDumpOnOutOfMemoryError | dump堆快照 |
运行结果:
引用
可以使用eclipse memory analyzer这个Jvm堆分析内存泄漏或者溢出的原因.
eclipse memory analyzer update url:
http://download.eclipse.org/mat/1.1/update-site/
如果内存泄漏可以看卡泄漏对象到GC Roots的引用链,从而分析出泄漏的代码位置。我们可从下图看出OOMObject占用大量堆空间。
如果是内存溢出,那就是说内存中的对象都应该存在着,那就检查虚拟机参数-Xmx与-Xms是否可以变大。
eclipse memory analyzer dominator tree 视图
Shallow heap | 对象自身占用的heap空间,不包括它引用的对象 |
Retained heap | 前对象+当前对象可直接或间接引用到的对象总体所占用的空间 |
其他与jvm内存空间相关参数
-Xss | 设置虚拟机栈和本地方法栈的大小 |
-XX:PermSize | 方法区最小空间 |
-XX:MaxPermSize | 方法区最大空间 |
栈溢出
public class JavaVMStackOOM
{
private int stackLength = 1;
public void stackLeak()
{
stackLength++;
stackLeak();
}
/**
* vm args -Xss128k
*/
public static void main(String[] args)
{
JavaVMStackOOM stackOOM = new JavaVMStackOOM();
stackOOM.stackLeak();
}
}
运行时常量池溢出
public class ConstantsPoolOOM
{
/**
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public static void main(String[] args)
{
List<String> list = new ArrayList<String>();
int i = 0;
while (true)
{
list.add(String.valueOf(i++).intern());
}
}
}
方法区异常
public class MethodAreaOOM
{
/**
* VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M
*/
public static void main(String[] args)
{
while (true)
{
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OOMObject.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor()
{
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable
{
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
static class OOMObject
{
}
}
本机直接内存溢出
public class DirectMemoryOOM
{
private static final int _1MB = 1024 * 1024;
/**
* VM Args: -Xmx20M -XX:MaxDirectMemorySize=10M
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException
{
Field unsafeFiled = Unsafe.class.getDeclaredFields()[0];
unsafeFiled.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeFiled.get(null);
while (true)
{
unsafe.allocateMemory(_1MB);
}
}
}
- 大小: 12 KB
- 大小: 20.5 KB
- 大小: 8.2 KB
- 大小: 37.8 KB
分享到:
相关推荐
JVM 内存区域组成包括栈内存和堆内存。栈内存用于存放基本类型变量和对象的引用变量,而堆内存用于存放由 new 创建的对象和数组。堆的优势是可以动态分配内存大小,生存期也不必事先告诉编译器,但缺点是要在运行时...
### JVM内存空间分配详解 #### 一、JVM内存模型概览 JVM(Java虚拟机)内存模型主要由以下几个部分组成:程序计数器、Java虚拟机栈、本地方法栈、Java堆以及方法区(在JDK 8之后称为元空间)。下面将对这几个部分...
《深入理解IDEA插件JProfiler11:高效优化JVM内存》 在Java开发领域,高效运行和优化JVM内存是至关重要的。IntelliJ IDEA(简称Idea)作为广受欢迎的Java集成开发环境,提供了一系列强大的工具来帮助开发者进行性能...
JVM内存分为几个关键区域,每个区域都有特定的功能和作用。这些区域包括: - **程序计数器(PC Register)**:每个线程都有自己独立的程序计数器,用于记录当前线程执行的字节码的行号。在方法调用、异常处理等过程...
JVM内存模型深度剖析与优化 JVM内存模型是Java虚拟机的核心组件之一,它直接影响着Java应用程序的性能和可靠性。本文将深入剖析JVM内存模型的结构和工作机理,并讨论如何优化JVM参数以提高Java应用程序的性能。 一...
在这份由Sun Microsystems公司出版的《JVM内存管理白皮书》中,我们可以找到关于Java虚拟机(JVM)内存管理的详细介绍和深入分析。这份文档对于想要深入了解JVM工作原理的读者来说是一份宝贵的学习资料。在这份...
JVM内存主要分为以下几个区域: 1. **堆内存(Heap)**:这是程序共享的内存区域,用于存储对象实例和数组。 2. **方法区(Method Area)**:用于存储类的信息、静态变量、常量池等数据。 3. **栈内存(Stack)**:每个...
首先,JVM内存分配策略主要涉及对象如何在堆内存的不同区域进行分配。对象在新生代Eden区进行分配,这是内存分配最频繁的区域。为了减少内存分配时的线程同步问题,JVM引入了本地线程分配缓冲(TLAB),允许每个线程...
通过 jstat,你可以监控 JVM 各个区域的内存使用率,包括年轻代、老年代和永久代,这对于分析内存泄漏和优化 GC 参数至关重要。 #### jmap:内存映射和对象转储 jmap 工具用于打印 Java 进程的堆内存布局,包括...
MAT,全称Memory Analyzer Tool,是IBM开发的一款强大的Java虚拟机(JVM)内存分析工具,尤其适用于Mac OS X平台。这款工具可以帮助开发者诊断和解决Java应用中的内存泄漏问题,提高应用性能。MAT通过深入分析堆转储...
MAT JVM内存分析工具可以帮助开发者深入理解Java虚拟机(JVM)的内存管理机制,通过分析堆内存快照来识别内存消耗异常的情况。 首先,MAT提供了丰富的视图来帮助用户查看内存状态,例如“概述”视图可以快速了解堆...
### JVM内存配置优化 #### 一、理解JVM内存模型 在进行JVM内存配置优化之前,我们需要了解Java虚拟机(JVM)的内存结构。Java的逻辑内存模型大致分为几个部分: 1. **堆内存(Heap)**:主要用于存储对象实例、数组...
JVM 内存结构和 6 大区域 JVM 是 Java虚拟机,它是 Java 语言的核心组件之一,为 Java 程序提供了运行环境。JVM 的内存结构是 Java 程序的基础,它的设计和实现对 Java 程序的性能和可靠性产生了深远的影响。 JVM ...
jvm内存模型,jvm脑图,jvm调优,jvm垃圾回收算法,jvm垃圾回收器,逃逸算法等总结。
JVM 内存参数详解以及配置调优 JVM 内存参数是 Java 虚拟机中最重要的参数之一,它直接影响着 Java 应用程序的性能和稳定性。在这个资源中,我们将详细讨论 JVM 内存参数的配置和调优,包括 JVM 的结构、内存管理、...
- **堆内存**:这是JVM最大的内存区域,用于存储对象实例。堆内存分为新生代(Young Generation)、老年代(Tenured Generation)和持久代(Permanent Generation,Java 8后被元空间Metaspace替代)。 - **新生代*...
该文档描述了开发测试环境中Docker及JVM内存限制部署方案
JVM内存模型是Java虚拟机(JVM)中的一种内存管理机制,它将内存区分为永久区内存(Permanent space)和堆内存(heap space)两大块。永久区内存用于存放加载的Class类级对象,如class本身、method、field等等,而堆...