JVM
子翊寒
放开,请让我带你入门
展开
-
程序计数器
程序计数器先来看这张图,对于数据区,存在着线程,进程的概念。程序计数器是每个线程私有的。如果没有多线程的概念,可以直接无视。程序计数器程序计数器,也有人叫它 程序寄存器。但是叫做 程序计数器更为精确。因为我们知道,在计算机也有一种结构叫做 寄存器,它储存容量小,但是速度快,一般用于 CPU 中。但是我们这里的 程序计数器 只是我们常说的内存中划分出的一块小内存区域,用来充当 程序计数器的功能。它记录了,我们下一条要运行指令的地址。我们来看这张图。右边是我们从 Java 文件编译出的 cl原创 2020-06-24 15:19:49 · 800 阅读 · 0 评论 -
Java 虚拟机栈
栈结构栈,这种数据结构,太重要了。如果学习过算法,就可以了解它的强大了。栈,就像我们叠起来的盘子,只能对最上面的部分进行操作。对于栈,只有两种操作:入栈,在上面再加一个盘子出栈,拿掉最上面的盘子别小看这两种操作,他可以完成很多复杂的事情,这就是数据结构和算法的魅力。JVM 的运行是基于栈的指令集,也就是说,JVM 对于数据的操作,都是基于栈这种数据结构的。栈指令集我们写一段代码:package runningDate;public class JavaStackTest {原创 2020-06-24 16:19:01 · 366 阅读 · 0 评论 -
运行时数据区
按理说,在介绍完前端编译器之后,我们应该介绍如何让 JVM 去解释运行 这个编译后的 .class 文件。但是感觉并不是很恰当。如果把 .class 文件比做新购买的家具,那么如果需要把家具摆放到家里,是不是得先了解房子的结构和布局,然后才能将家具进行正确的摆放。我们这里介绍的 运行时数据区 相当于前面提到的 房子结构。运行时数据区,这个名字实在取得太高大上了。其实就是,当我们程序运行的时候,这一块区域主要是负责数据的处理。程序的基本逻辑,无非就是不同的数据进行交互。在这块 数据区 中,有很多不原创 2020-06-24 14:57:43 · 200 阅读 · 0 评论 -
前端编译
前端编译的主要作用,是将 我们编写的 .java 文件 编译成 .class 文件,也就是我们常说的 字节码 文件。字节码 文件,里面包含了我们编写的 .java 代码中的运行逻辑,参数 以及 这些参数在内存中的分配。前端编译过程解析与填充符号表注解处理分析与字节码生成总而言之,就是对 .java 文件进行语法分析,根据 .java 文件构建抽象语法树。前端编译结果package methodArea;public class MethodTest { public stat原创 2020-06-24 14:04:57 · 1576 阅读 · 0 评论 -
方法区概述
方法区概述首先先来说说 方法区 的作用。方法区方法区,是用来存放有关 类、方法 信息的一块逻辑上的区域。也就说,人们想规划出一块区域,用来存储类 方法 相关信息。除此之外,还用来存储常量、静态变量,以及一些代码缓存等数据。想想,这些数据都有什么特点。几乎不变;不怎么依赖于对象,独立。方法区的故事关于方法区,有很多的故事 和 混乱。方法区、永久代、元空间都跟他有着故事。故事的缘由是由历史和部分概念不清晰导致的。我们之前说到,方法区 只是一个逻辑上的概念。具体的实现,叫做 永久代 和 元空原创 2020-06-24 10:31:27 · 2447 阅读 · 0 评论 -
常见测试堆空间的 JVM 参数
-XX:+PrintFlagsInital 查看所有参数的初始值-XX:+PrintFlagsFinal 查看所有参数的最终值-Xms 设置堆的初始值-Xmx 设置堆的最大值-Xmn 设置新生代的大小-XX:NewRatio 新生代与老年代的比例-XX:SurvivorRatio 设置 Eden 和 Survivor 比例-XX:MaxTenuringThreshold 设置进入老年代的年龄阈值-XX:+PrintGCDetails 打印 垃圾回收 的细节-XX:HandlerPromot原创 2020-06-23 00:08:24 · 168 阅读 · 0 评论 -
对象创建与堆
这一节主要介绍对象创建时,在堆中的一些过程。回忆下,我们之前说的,什么时候会发生垃圾回收?除了在一些安全点处也许会发生垃圾回收(只是也许),如果在所需内存不足的情况下,一定会发生垃圾回收。分配堆空间首先通过设置参数,把堆空间设置为 20M,其中 新生代 10M,老年代 10M。参数设置:-Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails结果为:Heap PSYoungGen total 9216K, used 1685K [0x00000007原创 2020-06-22 23:40:35 · 228 阅读 · 0 评论 -
对象的内存布局
对象的内存布局创建一个对象,不仅仅是找一块内存区域,然后把对象的值赋值进去那么简单。你想想,当我们 new 一个对象出来的时候,我们可以利用反射获取对象的一些信息。可以通过对象调用其中的一些方法。所以,在内存中,对象不仅仅包含了对象值那么简单,它还包含了更多的信息。这些信息保存在一个名为 对象头 的结构中。对象头一个对象实例,包含了 对象头、实例数据 和 对齐填充。对象头主要保存了这个实例的一些信息,实例数据保存了其中的实例数据。最后的 对齐填充,只是为了单纯填充空间。可以从图上看到,对象头主原创 2020-06-22 14:54:26 · 184 阅读 · 0 评论 -
基于分代的堆结构
堆的结构是基于分代理论(垃圾回收)的,这种结构划分,是为了更好地进行垃圾回收。我们将堆分为老年代、新生代。永久代、元空间、堆这几个概念一直比较混乱。但是看到上图,堆的定义只包含 新生代 和 老年代。这一点我们在实际设置 JVM 的参数的时候,你会发现,设置的空间的确只包含 新生代 和 老年代。新生代 和 老年代 是根据对象的生命周期特点来区别的。堆参数的设置接下来,我们来看下 Java 8 中,关于 堆 参数的设置:-Xms:表示堆的起始内存-Xmx:表示堆的最大内存一旦堆需要的空间大于原创 2020-06-22 12:47:14 · 196 阅读 · 0 评论 -
强软弱虚引用
强软弱虚,是 Java 中比较主流的四种引用。(多念念,就顺口了)从这四种引用的作用来看(接下来你会看到),引用,与对象的存活密不可分。也许正是因为有了 JVM 的垃圾收集器,才有了这四种引用。我觉得直接看四种引用的概念比较好:强引用;无论何时,只要有强引用关系的对象,都不会被垃圾回收器回收掉,如果内存不足的时候,直接报错软引用:有软引用关系的对象,当内存即将不足的时候,会被垃圾回收器清理掉;弱引用:有弱引用关系的对象,只能活到下一次垃圾回收的时候,也就是,只要发生了一次垃圾回收,那么弱引用关系原创 2020-06-21 19:05:15 · 236 阅读 · 0 评论 -
安全点和安全区域
前面介绍了垃圾回收器几个方面的内容:如何标记垃圾如何处理垃圾那么还有什么问题要解决呢?既然是自动垃圾回收,那么自动是什么情况呢?在我看来,自动主要来自两个方面:当我们年轻代、老年代内存不足时,触发某种条件,进行垃圾收集还有一个就是我们接下来说的安全点、安全区域安全点为什么要有安全点呢?在一个程序执行过程中,我们不一定要等到内存不足的时候,再进行垃圾回收整理。如果只是等待到内存不足的时候再进行整理,那么这个时候,就会有大量的垃圾,那么处理起来,要耗费的时间就会增长。所以,为了减原创 2020-06-21 15:36:09 · 569 阅读 · 0 评论 -
垃圾回收算法
前面介绍了如何去识别和标记垃圾,现在主要介绍,如何去回收(处理、删除)这些垃圾?你也许会想,找到了直接删掉不就行了吗?恭喜你,已经学会了一个很重要的算法。标记-清除(Mark-Sweep)标记-清除算法,主要分为两个步骤,标记 和 清除。标记,就使用之前说过的 可达性分析算法,即可进行标记。就是我们根据 GC Roots 标记出存活对象,然后将垃圾对象进行清除即可。就是这么简单。但是这种算法主要有如下缺点:会产生大量的内存碎片。内存空间不再连续,对于一些大对象连续的对象结构来说,无非是浪费原创 2020-06-21 14:02:08 · 215 阅读 · 0 评论 -
垃圾回收相关算法
这里介绍的垃圾回收相关算法,主要解决的问题:判断哪些内存是垃圾(需要回收的)?常用的两种算法:引用计数可达性分析(GC Root)首先介绍算法前,得定义:如何判断一个对象的死亡?我们一般这样定义:当一个对象不再被任何存活的对象继续引用的时候,这个对象就死亡了。引用计数引用计数算法,是给每一个对象添加一个计数器,当有对象引用它的时候,计数器+1,当有对象取消对它的引用时,计数就会-1。当计数器的值为 0 时,即说明没有对象引用它,也就是这个对象死亡了。这种算法很简单,但是有个原创 2020-06-21 11:14:07 · 197 阅读 · 0 评论