上篇说到了关于java heap的一些特征:连续的内存区域,逐步扩张的特征和如何做的这点的。but在讨论JVM的堆内存的细节以及垃圾回收等事宜之前,我们先讨论一下java进程的内存结构。
郁闷,
昨日
这一篇本来写完了,但是提交失败了。。。
只好再写了,简略些吧,继续正题:
通常我们所关注JVM的内存区域是java heap(堆),比如有时发生内存泄露(memory leak),或者内存溢出(out of
memory)的问题,让我们不得不把堆的问题弄透彻。先提一个入门的小问题,而为什么c/c++就不用关注这个呢(它也有堆内存的申请)?那是因为,
java语言为了让开发者省事,在语言设计上就没有提供内存释放的语句(比如delete/free那样的)并强制大家使用,而是采用了程序只管创建(
new
)对象即可,由JVM的Garbage collector全权负责回收无用的对象的方式。与c/c++那样的构造/析构方式相比,两者各有利弊,此处不再废话。
然而堆内存只是java进程所占内存空间上的一部分,JVM还有哪些主要的内存区域呢?
首先是JVM native code
segment
,这部分内存空间被jvm中各部件的二进制执行代码所占据,属于固定开销,我们无法更改或影响其所占的大小,具体都有哪些部件呢,如执行引
擎即解释器(exec engine/interpreter)、class
loader、内存管理器、gc器、jit编译器、与OS的接口(主要有6大类:System/Memory/Library/Thread/File/Socket)等(这些部件都是老虎屁股,摸不得的);其次,是Java stack(栈
)
,
是解释器用于解释执行字节码指令的工作区域,也是本地变量的藏身之处(不明白什么是本地变量请自己翻书),一般每线程拥有独立的一段,如果线程很多,函数
调用深度很深,本地变量繁多,那么,java stack自然庞大,另外,为了防止java
stack开销过大,一个线程的调用深度是有限制(一般jvm命令行可指定)的,超过了就会发生stack overflow,要说明的是,java
stack是jvm native heap的一部分,当然,java heap也是
jvm native heap的
一部分;第三,与java stack相仿的是native
stack
,不过它可不包含在jvm native
heap之中,这是来自于jvm自身组件和native函数的普通code(非字节码的哦)在函数调用时必须要用到的栈(学过汇编语言的,这些都不难理
解),这部分内存我们也无能为力;还有一部分重要的区域是method area
,这部分内存存放了所有已加载class的字节码(注意class
loader加载某类时,还会产生该类唯一的一个java.lang.Class实例,它存在于java
heap中),这部分内存大小和系统运行时需要运行的类和代码的多寡有关,而它也不是一成不变的,当class
gc不被禁止时,如果某类的Class对象实例被gc时,其method
data也将被清除,而jit编译器或者hotspot编译器在运行时也会改动它们(以后再探讨这部分),显而易见,method area是jvm
native heap中的一块;加上java heap以及class manifest等,jvm的内存基本上可以按以上划分区域,切个图表示一下吧
。言多必失,各类jvm实现毕竟有所不同,而jvm规范又总是比较abstract。
再来说一下你的程序运行时,数据都存储在哪里(此时你也该明白了吧)。不考虑有native方法的情形(以后再细说它),那么:
- class中的byte
code会放在method
area中(不用担心实例方法的重合,实例方法并不特殊于静态方法,只不过第一个参数隐含是this,而jvm用数字给本地变量命名,this的终身编号
总是1);
- 本地变量(
local variable
)的值
(对于原生类型,就是数据本身,若是引用类型则只是它的引用指针值,下同)存在于java stack中;
- 而所有的
成员变量(instance field和static field)的值
和
所有的对象实例(Object,注意也包含一个class的Class对象)本身
都存在于java heap中
。
总的看来,大批量的数据(尤其是生命周期不长的动态的数据)还是存放在java heap上的,对于java
heap,一个看似矛盾的事实是,原生数据(primitive)无法直接存在于java heap上,而java heap却主要地存放着它们。后面将专门写一篇关于java heap的。
编末:重写一遍,和原来的内容大相径庭啊,不过神没散就成。
从以上,我们基本可以先得出一部分best practices:
- 缩减你的系统中class的总个数。jvm随着版本升级,越来越庞大了,单是一个xml parser,类的个数已经成百上千。多一个类,意味着在java heap之外,仍然多一份内存开销。当你看到一个系统一开始运行就装载上万个class时,你的心情一定不轻松。
- 降低类之间的关联度,包括继承、域引用和方法调用,静态域也要注意释放(赋值为null),不仅在类加载和初始化获得效率,对于服务器程序来说,也使得class gc能够顺利进行。在多线程、热部署、长时间运行的大型环境下,稍不留神,JVM里就会发生极其龌龊的事情。
再次修改注:静态变量也是在java heap上的,原稿误解了。
分享到:
相关推荐
《深入Java虚拟机》(Inside the Java Virtual Machine) 是一本深入了解Java编程语言核心以及Java虚拟机(JVM)工作原理的经典书籍。这本书分为第一版和第二版,分别提供了当时最新的JVM技术解析。 首先,我们要了解...
Eclipse Memory Analyzer(MAT)是一款强大的Java内存分析工具,它被广泛用于诊断和解决Java应用程序中的内存泄漏问题。MAT 1.8.1是适用于macOS的特定版本,旨在帮助开发者深入理解并优化他们的Java应用内存使用情况...
Java.lang.OutOfMemoryError: Java heap space 是 Java 中的一个常见错误,它发生时,Java 虚拟机 (JVM) 无法分配对象,因为堆空间不足。下面是解决该问题的一些方法: 原因分析 1. Java 虚拟机 (JVM) 内存过小:...
java.lang.OutOfMemoryError是Java虚拟机(JVM)中的一种常见错误,发生这种错误时,JVM将无法继续运行,程序将崩溃。这种错误的出现通常是由于Jvm的内存不足或内存泄露导致的。 出现java.lang.OutOfMemoryError的...
这类异常通常表明Java虚拟机(JVM)在运行过程中遇到了内存不足的问题,特别是当堆内存无法满足程序的需求时。 #### 二、原因分析 1. **项目规模过大**:如果项目中的类文件数量过多或者单个对象占用内存较大时,...
这个错误表明Java虚拟机(JVM)没有足够的内存来创建新的对象,这可能是由于程序设计导致的内存泄漏,或者是对大对象的不当处理,或者是分配给Java应用的堆内存不足。 为了解决这个问题,我们需要深入理解Java内存...
在Java中,这主要与JVM(Java虚拟机)的内存模型有关,该模型包括堆(Heap)、栈(Stack)、方法区(Method Area)和程序计数器(PC Register)等几个区域。当堆或方法区的内存耗尽时,就会抛出`OutOfMemoryError`。...
"JVM Memory View"工具,版本号为0.93.162,就是针对这一需求而设计的JVM调试内存查看器,专为Android Studio用户提供了一个直观、高效的内存分析解决方案。 一、JVM内存概述 Java虚拟机内存主要分为以下几个区域...
JVM(Java虚拟机)是Java平台的核心组件,提供了一个抽象的计算环境,使得Java程序能够在不同的操作系统上运行,实现平台独立性。JVM将Java程序编译成特定的二进制格式——类文件格式,使得Java虚拟机本身对Java编程...
Java虚拟机(JVM)内存管理与调优是Java开发中的关键环节,它涉及到程序的性能、稳定性和资源效率。JVM内存分为多个区域,包括堆内存、方法区、程序计数器、虚拟机栈和本地方法栈。理解这些区域的工作原理以及如何...
这种异常通常发生在应用程序占用的堆内存超过了Java虚拟机(JVM)分配给它的最大堆内存限制时。本文将详细介绍该问题产生的原因以及如何有效地解决它。 #### 一、问题分析 1. **异常含义**: - `java.lang....
它包含了Java虚拟机(JVM)、Java类库以及用于构建和运行Java应用程序的工具。对于Windows x64平台,JDK 21优化了内存管理,支持多核处理器,确保在64位环境下运行更加流畅。 二、安装与配置 1. 下载:首先,从...
PermGen(Permanent Generation)是Java虚拟机(JVM)的一个内存区域,主要用于存储类的元数据,如类的名称、方法信息等。与堆区不同,堆区中的对象在不再被引用时会被垃圾收集器(Garbage Collector, GC)回收,但...
Java虚拟机(JVM)是Java程序运行的核心组件,它负责解释和执行字节码,为Java应用程序提供了一个跨平台的运行环境。《JAVA8虚拟机(jvm)规范_Chinese version》提供了关于JVM的详细中文指南,对于理解Java程序的运行...
总之,"java.lang.OutOfMemoryError: PermGen space"错误是由于Java虚拟机的 PermGen 区域内存不足造成的,可以通过增大 PermGen 区域的大小、升级JVM版本、优化类加载和库的使用等方式来解决。对于任何内存管理问题...
它将.java文件编译成.class文件,这些文件包含了Java虚拟机(JVM)能够理解的机器无关的指令。 2. **Java运行环境(JRE)**:JRE是Java程序运行的基础,它包括Java虚拟机、Java类库和其他支持Java程序运行的组件。...
- **内存使用**:JVM内存的分配和使用,包括堆内存(Heap Memory)和非堆内存(Non-Heap Memory),过高可能导致垃圾回收频繁或内存溢出。 - **线程活动**:检查活跃线程数量,过多可能意味着潜在的线程阻塞或死锁...
在Java开发领域,JVM(Java Virtual Machine)是运行Java应用程序的关键组件,它负责解析字节码并执行程序。JVM调优是一项重要的技能,它能够帮助提升应用性能、减少内存消耗以及改善整体系统稳定性。"jvm调优学习-...
在Java开发中,JVM(Java Virtual Machine)性能调优是提升应用程序效率的关键环节。JVM内存模型的理解和优化,对于解决性能瓶颈、避免内存泄漏以及提高系统稳定性至关重要。本文将详细探讨JVM的内存结构,以及如何...
Java虚拟机(JVM)是Java开发的核心组成部分,它负责执行Java程序并管理内存。面试中,JVM的深入理解是衡量开发者技能的关键指标。以下是对JVM内存模型及其相关知识点的详细阐述: 1. **内存模型及分区**: - **...