本文概述
- JVM内存结构
- 垃圾收集器的工作
- 标记和扫描算法
- JVM内存结构
- 垃圾收集器的工作
文章图片
方法范围
方法区域是堆内存的一部分, 在所有线程之间共享。它在JVM启动时创建。它用于存储类结构, 超类名称, 接口名称和构造函数。 JVM在方法区域中存储以下信息:
- 类型的完全限定名称(例如:字符串)
- 类型的修饰符
- 类型的直接超类名称
- 超级接口的完全限定名称的结构化列表。
堆存储实际对象。它在JVM启动时创建。如果需要, 用户可以控制堆。它可以是固定大小或动态大小。当你使用new关键字时, JVM将为堆中的对象创建一个实例。而该对象的引用存储在堆栈中。每个运行的JVM进程只有一个堆。当堆变满时, 将收集垃圾。例如:
StringBuilder sb= new StringBuilder();
上面的语句创建StringBuilder类的对象。该对象分配给堆, 引用sb分配给堆栈。堆分为以下部分:
- 年轻一代
- 幸存空间
- 老一代
- 永久的一代
- 缓存代码
引用有四种类型:强引用, 弱引用, 软引用和幻像引用。引用类型之间的区别在于, 它们引用的堆上的对象可以在不同条件下进行垃圾收集。
有力的参考:在日常编程中使用它非常简单。附加了“强引用”的任何对象均不符合垃圾回收的条件。我们可以使用以下语句来创建强大的参考:
StringBuilder sb= new StringBuilder();
弱引用:在下一个垃圾回收过程之后, 它将无法生存。如果我们不确定何时会再次请求数据。在这种情况下, 我们可以为其创建一个弱引用。以防万一, 如果垃圾回收器进行处理, 它将破坏该对象。当我们再次尝试检索该对象时, 我们得到一个空值。它在java.lang.ref.WeakReference类中定义。我们可以使用以下语句创建一个弱引用:
WeakReference<
StringBuilder>
reference = new WeakReference<
>
(new StringBuilder());
软参考:当应用程序内存不足时收集。垃圾收集器不会收集柔软可触及的对象。所有软引用的对象s都会在抛出OutOfMemoryError之前被收集。我们可以使用以下语句创建一个软引用:
SoftReference<
StringBuilder>
reference = new SoftReference<
>
(new StringBuilder());
幻像参考:它在java.lang.ref包中可用。它在java.lang.ref.PhantomReference类中定义。只要垃圾收集器想要收集, 就可以收集只有幻像引用指向它们的对象。我们可以使用以下语句创建幻像引用:
PhantomReference<
StringBuilder>
reference = new PhantomReference<
>
(new StringBuilder());
堆叠面积
创建线程时会生成堆栈区域。它可以是固定大小, 也可以是动态大小。堆栈内存是按线程分配的。它用于存储数据和部分结果。它包含对堆对象的引用。它还保留值本身, 而不是对堆中对象的引用。存储在堆栈中的变量具有一定的可见性, 称为作用域。
堆栈框架:堆栈框架是一种包含线程数据的数据结构。线程数据表示当前方法中线程的状态。
- 它用于存储部分结果和数据。它还执行动态链接, 方法返回的值和调度异常。
- 调用方法时, 将创建一个新框架。方法调用完成后, 它将破坏框架。
- 每个帧都包含自己的局部变量数组(LVA), 操作数堆栈(OS)和帧数据(FD)。
- LVA, OS和FD的大小在编译时确定。
- 在给定的控制线程中的任何一点上, 只有一个框架(用于执行方法的框架)处于活动状态。该帧称为当前帧, 其方法称为当前方法。方法的类称为当前类。
- 如果框架的方法调用另一个方法或该方法完成, 则框架将停止当前方法。
- 线程创建的框架是该线程的本地框架, 任何其他线程都无法引用。
也称为C堆栈。它是使用非Java语言编写的本机代码的堆栈。 Java本机接口(JNI)调用本机堆栈。本机堆栈的性能取决于操作系统。
PC寄存器
每个线程都有一个与之关联的程序计数器(PC)寄存器。 PC寄存器存储返回地址或本机指针。它还包含当前正在执行的JVM指令的地址。
垃圾收集器的工作 垃圾收集器概述
当程序以Java执行时, 它以不同的方式使用内存。堆是对象所在的内存的一部分。它是垃圾收集过程中唯一的内存部分。也称为垃圾可收集堆。所有垃圾收集都确保堆具有尽可能多的可用空间。垃圾收集器的功能是查找和删除无法访问的对象。
对象分配
分配对象时, JRockit JVM将检查对象的大小。它区分大小物体。大小取决于JVM版本, 堆大小, 垃圾回收策略以及所使用的平台。对象的大小通常在2到128 KB之间。
小对象存储在线程本地区域(TLA)中, 该区域是堆的空闲块。 TLA不与其他线程同步。当TLA变满时, 它将请求新的TLA。
另一方面, 不适用于TLA的大对象直接分配到堆中。如果线程正在使用年轻空间, 那么它将直接存储在旧空间中。大对象需要线程之间更多的同步。
Java垃圾收集器是什么?
JVM控制垃圾收集器。 JVM决定何时执行垃圾回收。我们还可以请求JVM运行垃圾回收器。但是, 在任何情况下都无法保证JVM会遵守。如果JVM感觉到内存不足, 则运行垃圾回收器。当Java程序请求垃圾收集器时, JVM通常以短顺序授予该请求。它不能确保请求接受。
要理解的重点是“什么时候对象可以进行垃圾收集?”
每个Java程序都有多个线程。每个线程都有其执行堆栈。在Java程序中有一个要运行的线程是main()方法。现在我们可以说, 当没有活动线程访问对象时, 该对象就有资格进行垃圾回收。垃圾收集器认为该对象符合删除条件。如果程序具有引用对象的引用变量, 该引用变量可用于活动线程, 则该对象称为可达对象。
这里出现一个问题, 即“ Java应用程序是否会耗尽内存?”
答案是肯定的。垃圾收集系统在不使用对象时会尝试从内存中获取对象。但是, 如果要维护许多活动对象, 则垃圾回收不能保证有足够的内存。仅可用内存将得到有效管理。
垃圾收集的类型
垃圾收集有五种类型, 如下所示:
- 串行GC:它采用标记和清除方法, 适用于年少的GC和主要的GC。
- 并行GC:与串行GC相似, 不同之处在于, 它生成N(系统中CPU核心数)个线程用于年轻一代的垃圾回收。
- 并行旧式GC:与并行GC相似, 不同之处在于, 两代均使用多个线程。
- 并发标记扫描(CMS)收集器:它为旧一代进行垃圾收集。你可以使用XX:ParalleCMSThreads = JVM选项限制CMS收集器中的线程数。它也被称为并发低暂停收集器。
- G1垃圾收集器:它是Java 7中引入的。其目标是替换CMS收集器。它是一个并行, 并发和CMS收集器。没有年轻人和老年人的空间。它将堆分成几个相等大小的堆。它首先收集实时数据较少的区域。
标记阶段:可从线程, 本机句柄和其他GC根源访问的对象标记为活动。每个对象树都有多个根对象。 GC根始终是可访问的。因此, 任何在其根上具有垃圾回收根的对象。它标识并标记所有正在使用的对象, 其余的可以视为垃圾。
文章图片
扫描阶段:在此阶段, 遍历堆以查找活动对象之间的间隙。这些间隔记录在空闲列表中, 可用于新对象分配。
标记和清除有两个改进的版本:
- 并发标记和扫描
- 平行标记和扫掠
它允许线程在大部分垃圾回收期间继续运行。有以下几种标记类型:
- 初始标记:它标识活动对象的根集。它是在线程暂停时完成的。
- 并发标记:在此标记中, 遵循根集中的引用。它查找并标记堆中其余的活动对象。它是在线程运行时完成的。
- 清洗前标记:它标识并发标记所做的更改。标记并找到其他活动对象。它是在线程运行时完成的。
- 最终标记:它标识了通过预清洁标记所做的更改。标记并找到其他活动对象。它是在线程暂停时完成的。
它使用系统中所有可用的CPU来尽快执行垃圾回收。它也称为并行垃圾收集器。当并行垃圾回收执行时, 线程不执行。
Mark and Sweep的优点
- 这是一个重复的过程。
- 这是一个无限循环。
- 在算法执行期间不允许额外的开销。
- 当垃圾收集算法运行时, 它将停止正常程序执行。
- 它在一个程序上运行多次。
推荐阅读
- Java中的NumberFormatException
- Java中的NoSuchElementException
- 常见的Windows 11问题和解决方法(提示和指南)
- 6款适用于Chromebook(Chrome替代品)的最佳浏览器合集
- 如何修复无法重置Windows 11的问题(详细分步指南)
- win8.1打开Media Player播放器提示“Failed to load control ”怎样办
- Win8怎样运用自带的GeoLocation地理定位技巧【图文详细教程】
- win8.1系统搜索文件时遇到同一个文件重复显示怎样办
- Win 8系统连接网络失败提示出错711如何处理