本文概述
在Java中, 堆是在所有线程之间共享的一块内存。在堆中, 将分配所有类实例和数组。它是在JVM启动时创建的。自动存储管理系统回收堆。它的大小可以是固定的, 也可以是可变的。它不需要是连续的。
堆结构
堆分为两部分(或几代):
- 年轻一代(或年轻空间或苗圃)
- 老一代(或老空间或终身制)
年轻一代
它是堆的一部分。保留用于分配对象。装满后, 次要GC将垃圾从Eden收集到幸存者空间之一。清除其中一个幸存者空间中可用于垃圾的对象, 并将其余对象移至另一个幸存者空间。因此, 总是有一个空的幸存者空间。在年轻空间中长寿的所有物体都将转移到旧空间。
Java的最新发行版中有一部分内容称为Keep Area。它包含托儿所中最近分配的对象。它直到下一代才收集垃圾。
- 伊甸园:首先在这里创建所有对象。它比两个幸存者空间大。它占用了年轻一代76%的空间。当Eden充满时, 将触发次要GC。
- 幸存者空间:它是在伊甸园空间的垃圾收集中幸存下来的一组对象。从(S0)有两个幸存者空间, 称为(S1)的幸存者空间。它避免了内存碎片。关于幸存者的要点是, 两个幸存者之一始终是空的。
整个年轻一代的所有活动物(伊甸园空间+太空中的幸存者)都移到了生存者到太空中。完成此过程后, 太空中的幸存者是空的。在幸存者空间之间复制活动对象的过程重复进行几次, 直到某些对象被认为已经成熟并且足够老为止。因此, 此类物体可以移动到旧空间, 而不是移动到其他幸存者空间。为了确定对象是否准备好移入旧空间, GC会对对象幸存的集合总数进行计数。如果不收集, 则对象的寿命会增加。
旧空间
它包含寿命长的对象。此过程称为旧集合。经过数轮次要GC检验后, 长寿对象得以幸存。当旧空间即将达到极限时, 将清除旧内存的主要资源。通常, 垃圾回收器会在达到其极限时在旧一代中执行。旧的垃圾收集器称为主要GC。移除对象花费的时间太长。
这里出现一个问题:“如果老一代的对象需要引用年轻一代的对象, 会发生什么?”
为了处理这种情况, JVM在旧版本中管理一个称为卡表的表。它是一个512字节的内存块。当老一代中的对象引用年轻一代中的对象时, 它将记录在卡表中。当年轻一代执行次要GC时, GC仅搜索该表。它确定它是否适用于GC, 而不是检查旧版本中所有对象的引用。写屏障管理卡表。该设备可提高次要GC的性能。
非堆内存
它包括一个在所有线程之间共享的方法区域。它存储每个类的结构。它的大小可以固定或可变。它不需要是连续的。
永久世代(PermGen)
JVM在运行时生成它。它包含JVM所需的应用程序元数据。元数据包括应用程序中使用的类和方法。它还包括Java SE库类和方法。
元空间在Java 8中替换了它。这意味着在Java 8中不会发生java.lang.OutOfMemoryError。在元空间中引入了两个新标志, 它们是:-XXMetasapceSize和?XXMaxMetaspaceSize。元空间的主要动机是, 只要类加载器处于活动状态, 元数据就在元空间中保持活动状态。
PermGen和元空间之间的主要区别是:PermGen是堆的一部分, 而元空间是本机内存的一部分。
代码缓存:这是与堆分开的内存区域。它用于本机代码的编译和存储。这是一个固定大小的空间。如果已满, JVM将不会编译任何其他代码。为避免这种情况, 可以使用以下大小选项调整代码缓存:
- InitialCodeCacheSize:其默认大小(字节)为160K。
- ReservedCacheSize:其默认最大大小为48M。
- CodeCacheExpansionSize:其默认大小为32K或64K。
JVM使用“使用代码缓存刷新”选项来控制代码缓存区域的刷新。其默认值为false。即时(JIT)编译器是代码缓存区域的最大用户。
java.lang.OutOfMemoryError的原因
当应用程序尝试向堆空间区域中添加更多数据, 但没有足够的空间时, 将触发该错误。 JVM达到堆大小限制时将抛出Java堆空间错误。
- 数据量激增:这种情况是应用程序尝试将更多数据添加到堆空间中, 但没有足够的空间供其使用。
- 内存泄漏:这是一个编程错误, 导致你的应用程序连续消耗更多的内存。它可以以多种方式发生。当对象不再由应用程序使用但垃圾收集器无法识别它时, 这是一种情况。你可以使用内存管理工具(例如HP jmeter, JProbe和IBM Tivoli)来识别无用的对象和内存泄漏。
例
public class MemoryLeaksDemo
{
public static void main(String[] args)
{
int[] arr = new int[999999999]; //allocating memory to array
System.out.println("OutOfMemoryError");
}
}
输出:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at MemoryLeaksDemo.main(MemoryLeaksDemo.java:5)
评论前必须登录!
注册