当前位置: 首页 > news >正文

门户网站底部动漫设计师发展前景

门户网站底部,动漫设计师发展前景,深圳网站建设公,海南注册公司需要什么条件下文是阅读《深入理解Java虚拟机#xff08;第3版#xff09;》这本书的读书笔记#xff0c;如有侵权#xff0c;请联系删除。 文章目录 第2章 Java内存区域与内存溢出异常2.2 运行时数据区域2.3 HotSpot虚拟机对象探秘 第3章 垃圾收集器与内存分配策略3.2 对象已死第3版》这本书的读书笔记如有侵权请联系删除。 文章目录 第2章 Java内存区域与内存溢出异常2.2 运行时数据区域2.3 HotSpot虚拟机对象探秘 第3章 垃圾收集器与内存分配策略3.2 对象已死3.3 垃圾收集算法3.5 经典垃圾收集器3.6 低延迟垃圾收集器 后记 第2章 Java内存区域与内存溢出异常 2.2 运行时数据区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途以及创建和销毁的时间有的区域随着虚拟机进程的启动而一直存在有些区域则是依赖用户线程的启动和结束而建立和销毁。下图为Java虚拟机运行时数据区。 2.2.1 程序计数器 程序计数器Program Counter Register是一块较小的内存空间它可以看作是当前线程所执行的字节码的行号指示器。在Java虚拟机的概念模型里字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令它是程序控制流的指示器分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。 由于Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的在任何一个确定的时刻一个处理器对于多核处理器来说是一个内核都只会执行一条线程中的指令。因此为了线程切换后能恢复到正确的执行位置每条线程都需要有一个独立的程序计数器各条线程之间计数器互不影响独立存储我们称这类内存区域为“线程私有”的内存。 如果线程正在执行的是一个Java方法这个计数器记录的是正在执行的虚拟机字节码指令的地址如果正在执行的是本地Native方法这个计数器值则应为空Undefined。此内存区域是唯一一个在《Java虚拟机规范》中没有规定任何OutOfMemoryError情况的区域。 2.2.2 Java虚拟机栈 与程序计数器一样Java虚拟机栈Java Virtual MachineStack也是线程私有的它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的线程内存模型每个方法被执行的时候Java虚拟机都会同步创建一个栈帧Stack Frame用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 经常有人把Java内存区域笼统地划分为堆内存Heap和栈内存Stack这种划分方式直接继承自传统的C、C程序的内存布局结构在Java语言里就显得有些粗糙了实际的内存区域划分要比这更复杂。不过这种划分方式的流行也间接说明了程序员最关注的、与对象内存分配关系最密切的区域是“堆”和“栈”两块。其中“堆”在稍后笔者会专门讲述而“栈”通常就是指这里讲的虚拟机栈或者更多的情况下只是指虚拟机栈中局部变量表部分。 局部变量表存放了编译期可知的各种Java虚拟机基本数据类型boolean、byte、char、short、int、float、long、double、对象引用reference类型它并不等同于对象本身可能是一个指向对象起始地址的引用指针也可能是指向一个代表对象的句柄或者其他与此对象相关的位置和returnAddress类型指向了一条字节码指令的地址。 这些数据类型在局部变量表中的存储空间以局部变量槽Slot来表示其中64位长度的long和double类型的数据会占用两个变量槽其余的数据类型只占用一个。局部变量表所需的内存空间在编译期间完成分配当进入一个方法时这个方法需要在栈帧中分配多大的局部变量空间是完全确定的在方法运行期间不会改变局部变量表的大小。 2.2.3 本地方法栈 本地方法栈Native Method Stacks与虚拟机栈所发挥的作用是非常相似的其区别只是虚拟机栈为虚拟机执行Java方法也就是字节码服务而本地方法栈则是为虚拟机使用到的本地Native方法服务。 2.2.4 Java堆 对于Java应用程序来说Java堆Java Heap是虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例Java世界里“几乎”所有的对象实例都在这里分配内存。Java堆是垃圾收集器管理的内存区域因此一些资料中它也被称作“GC堆”Garbage Collected Heap幸好国内没翻译成“垃圾堆”。 2.2.5 方法区 方法区Method Area与Java堆一样是各个线程共享的内存区域它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。 2.2.6 运行时常量池 运行时常量池Runtime Constant Pool是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外还有一项信息是常量池表Constant Pool Table用于存放编译期生成的各种字面量与符号引用这部分内容将在类加载后存放到方法区的运行时常量池中。 Java虚拟机对于Class文件每一部分自然也包括常量池的格式都有严格规定如每一个字节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可、加载和执行但对于运行时常量池《Java虚拟机规范》并没有做任何细节的要求不同提供商实现的虚拟机可以按照自己的需要来实现这个内存区域不过一般来说除了保存Class文件中描述的符号引用外还会把由符号引用翻译出来的直接引用也存储在运行时常量池中。 运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性Java语言并不要求常量一定只有编译期才能产生也就是说并非预置入Class文件中常量池的内容才能进入方法区运行时常量池运行期间也可以将新的常量放入池中这种特性被开发人员利用得比较多的便是String类的intern()方法。 既然运行时常量池是方法区的一部分自然受到方法区内存的限制当常量池无法再申请到内存时会抛出OutOfMemoryError异常。 2.3 HotSpot虚拟机对象探秘 2.3.1 对象的创建 Java是一门面向对象的编程语言Java程序运行过程中无时无刻都有对象被创建出来。在语言层面上创建对象通常例外复制、反序列化仅仅是一个new关键字而已而在虚拟机中对象文中讨论的对象限于普通Java对象不包括数组和Class对象等的创建又是怎样一个过程呢 当Java虚拟机遇到一条字节码new指令时首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有那必须先执行相应的类加载过程。 在类加载检查通过后接下来虚拟机将为新生对象分配内存。对象所需内存的大小在类加载完成后便可完全确定为对象分配空间的任务实际上便等同于把一块确定大小的内存块从Java堆中划分出来。假设Java堆中内存是绝对规整的所有被使用过的内存都被放在一边空闲的内存被放在另一边中间放着一个指针作为分界点的指示器那所分配内存就仅仅是把那个指针向空闲空间方向挪动一段与对象大小相等的距离这种分配方式称为“指针碰撞”Bump The Pointer。但如果Java堆中的内存并不是规整的已被使用的内存和空闲的内存相互交错在一起那就没有办法简单地进行指针碰撞了虚拟机就必须维护一个列表记录上哪些内存块是可用的在分配的时候从列表中找到一块足够大的空间划分给对象实例并更新列表上的记录这种分配方式称为“空闲列表”Free List。选择哪种分配方式由Java堆是否规整决定而Java堆是否规整又由所采用的垃圾收集器是否带有空间压缩整理Compact的能力决定。因此当使用Serial、ParNew等带压缩整理过程的收集器时系统采用的分配算法是指针碰撞既简单又高效而当使用CMS这种基于清除Sweep算法的收集器时理论上就只能采用较为复杂的空闲列表来分配内存。 除如何划分可用空间之外还有另外一个需要考虑的问题对象创建在虚拟机中是非常频繁的行为即使仅仅修改一个指针所指向的位置在并发情况下也并不是线程安全的可能出现正在给对象A分配内存指针还没来得及修改对象B又同时使用了原来的指针来分配内存的情况。解决这个问题有两种可选方案一种是对分配内存空间的动作进行同步处理——实际上虚拟机是采用CAS配上失败重试的方式保证更新操作的原子性另外一种是把内存分配的动作按照线程划分在不同的空间之中进行即每个线程在Java堆中预先分配一小块内存称为本地线程分配缓冲Thread Local Allocation BufferTLAB哪个线程要分配内存就在哪个线程的本地缓冲区中分配只有本地缓冲区用完了分配新的缓存区时才需要同步锁定。虚拟机是否使用TLAB可以通过-XX/-UseTLAB参数来设定。 内存分配完成之后虚拟机必须将分配到的内存空间但不包括对象头都初始化为零值如果使用了TLAB的话这一项工作也可以提前至TLAB分配时顺便进行。这步操作保证了对象的实例字段在Java代码中可以不赋初始值就直接使用使程序能访问到这些字段的数据类型所对应的零值。 接下来Java虚拟机还要对对象进行必要的设置例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码实际上对象的哈希码会延后到真正调用Object::hashCode()方法时才计算、对象的GC分代年龄等信息。这些信息存放在对象的对象头Object Header之中。根据虚拟机当前运行状态的不同如是否启用偏向锁等对象头会有不同的设置方式。 在上面工作都完成之后从虚拟机的视角来看一个新的对象已经产生了。但是从Java程序的视角看来对象创建才刚刚开始——构造函数即Class文件中的()方法还没有执行所有的字段都为默认的零值对象需要的其他资源和状态信息也还没有按照预定的意图构造好。一般来说由字节码流中new指令后面是否跟随invokespecial指令所决定Java编译器会在遇到new关键字的地方同时生成这两条字节码指令但如果直接通过其他方式产生的则不一定如此new指令之后会接着执行()方法按照程序员的意愿对对象进行初始化这样一个真正可用的对象才算完全被构造出来。 2.3.2 对象的内存布局 在HotSpot虚拟机里对象在堆内存中的存储布局可以划分为三个部分对象头Header、实例数据Instance Data和对齐填充Padding。 HotSpot虚拟机对象的对象头部分包括两类信息。第一类是用于存储对象自身的运行时数据如哈希码HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等这部分数据的长度在32位和64位的虚拟机未开启压缩指针中分别为32个比特和64个比特官方称它为“MarkWord”。对象需要存储的运行时数据很多其实已经超出了32、64位Bitmap结构所能记录的最大限度但对象头里的信息是与对象自身定义的数据无关的额外存储成本考虑到虚拟机的空间效率Mark Word被设计成一个有着动态定义的数据结构以便在极小的空间内存储尽量多的数据根据对象的状态复用自己的存储空间。 对象头的另外一部分是类型指针即对象指向它的类型元数据的指针Java虚拟机通过这个指针来确定该对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针换句话说查找对象的元数据信息并不一定要经过对象本身。 接下来实例数据部分是对象真正存储的有效信息即我们在程序代码里面所定义的各种类型的字段内容无论是从父类继承下来的还是在子类中定义的字段都必须记录起来。 对象的第三部分是对齐填充这并不是必然存在的也没有特别的含义它仅仅起着占位符的作用。由于HotSpot虚拟机的自动内存管理系统要求对象起始地址必须是8字节的整数倍换句话说就是任何对象的大小都必须是8字节的整数倍。对象头部分已经被精心设计成正好是8字节的倍数1倍或者2倍因此如果对象实例数据部分没有对齐的话就需要通过对齐填充来补全。 2.3.3 对象的访问定位 创建对象自然是为了后续使用该对象我们的Java程序会通过栈上的reference数据来操作堆上的具体对象。由于reference类型在《Java虚拟机规范》里面只规定了它是一个指向对象的引用并没有定义这个引用应该通过什么方式去定位、访问到堆中对象的具体位置所以对象访问方式也是由虚拟机实现而定的主流的访问方式主要有使用句柄和直接指针两种 · 如果使用句柄访问的话Java堆中将可能会划分出一块内存来作为句柄池reference中存储的就是对象的句柄地址而句柄中包含了对象实例数据与类型数据各自具体的地址信息其结构如下图所示。 · 如果使用直接指针访问的话Java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息reference中存储的直接就是对象地址如果只是访问对象本身的话就不需要多一次间接访问的开销如下图所示。 这两种对象访问方式各有优势使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址在对象被移动垃圾收集时移动对象是非常普遍的行为)时只会改变句柄中的实例数据指针而reference本身不需要被修改。 使用直接指针来访问最大的好处就是速度更快它节省了一次指针定位的时间开销由于对象访问在Java中非常频繁因此这类开销积少成多也是一项极为可观的执行成本。 第3章 垃圾收集器与内存分配策略 3.2 对象已死 垃圾收集器在对堆进行回收前第一件事情就是要确定堆中对象之中哪些还“存活”着哪些已经“死去”“死去”即不可能再被任何途径使用的对象 3.2.1 引用计数算法 在对象中添加一个引用计数器每当有一个地方引用它时计数器值就加一当引用失效时计数器值就减一任何时刻计数器为零的对象就是不可能再被使用的。 局限单纯的引用计数就很难解决对象之间相互循环引用的问题。 3.2.2 可达性分析算法 这个算法的基本思路就是通过一系列称为“GC Roots”的根对象作为起始节点集从这些节点开始根据引用关系向下搜索搜索过程所走过的路径称为“引用链”Reference Chain如果某个对象到GC Roots间没有任何引用链相连或者用图论的话来说就是从GC Roots到这个对象不可达时则证明此对象是不可能再被使用的。下图为利用可达性分析算法判定对象是否可回收的例子。 3.3 垃圾收集算法 3.3.1 分代收集理论 当前商业虚拟机的垃圾收集器大多数都遵循了“分代收集”Generational Collection的理论进行设计分代收集名为理论实质是一套符合大多数程序运行实际情况的经验法则它建立在分代假说之上 1弱分代假说Weak Generational Hypothesis绝大多数对象都是朝生夕灭的。 2强分代假说Strong Generational Hypothesis熬过越多次垃圾收集过程的对象就越难以消亡。 3跨代引用假说Intergenerational Reference Hypothesis跨代引用相对于同代引用来说仅占极少数。 多款常用的垃圾收集器的一致的设计原则收集器应该将Java堆划分出不同的区域然后将回收对象依据其年龄年龄即对象熬过垃圾收集过程的次数分配到不同的区域之中存储。显而易见如果一个区域中大多数对象都是朝生夕灭难以熬过垃圾收集过程的话那么把它们集中放在一起每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象就能以较低代价回收到大量的空间如果剩下的都是难以消亡的对象那把它们集中放在一块虚拟机便可以使用较低的频率来回收这个区域这就同时兼顾了垃圾收集的时间开销和内存的空间有效利用。 把分代收集理论具体放到现在的商用Java虚拟机里设计者一般至少会把Java堆划分为新生代Young Generation 和 老年代Old Generation 两个区域。顾名思义在新生代中每次垃圾收集时都发现有大批对象死去而每次回收后存活的少量对象将会逐步晋升到老年代中存放。 3.3.2 标记-清除算法 算法分为“标记”和“清除”两个阶段首先标记出所有需要回收的对象在标记完成后统一回收掉所有被标记的对象也可以反过来标记存活的对象统一回收所有未被标记的对象。 它的主要缺点有两个第一个是执行效率不稳定如果Java堆中包含大量对象而且其中大部分是需要被回收的这时必须进行大量标记和清除的动作导致标记和清除两个过程的执行效率都随对象数量增长而降低第二个是内存空间的碎片化问题标记、清除之后会产生大量不连续的内存碎片空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。 3.3.3 标记-复制算法 标记-复制算法常被简称为复制算法。为了解决标记-清除算法面对大量可回收对象时执行效率低的问题1969年Fenichel提出了一种称为“半区复制”Semispace Copying的垃圾收集算法它将可用内存按容量划分为大小相等的两块每次只使用其中的一块。当这一块的内存用完了就将还存活着的对象复制到另外一块上面然后再把已使用过的内存空间一次清理掉。如果内存中多数对象都是存活的这种算法将会产生大量的内存间复制的开销但对于多数对象都是可回收的情况算法需要复制的就是占少数的存活对象而且每次都是针对整个半区进足够的连续内存而不得不提前触发另一次垃圾收集动作。 现在的商用Java虚拟机大多都优先采用了这种收集算法去回收新生代IBM公司曾有一项专门研究对新生代“朝生夕灭”的特点做了更量化的诠释——新生代中的对象有98%熬不过第一轮收集。因此并不需要按照1∶1的比例来划分新生代的内存空间。在1989年Andrew Appel针对具备“朝生夕灭”特点的对象提出了一种更优化的半区复制分代策略现在称为“Appel式回收”。 Appel式回收的具体做法是把新生代分为一块较大的Eden空间和两块较小的Survivor空间每次分配内存只使用Eden和其中一块Survivor。发生垃圾搜集时将Eden和Survivor中仍然存活的对象一次性复制到另外一块Survivor空间上然后直接清理掉Eden和已用过的那块Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是8∶1也即每次新生代中可用内存空间为整个新生代容量的90%Eden的80%加上一个Survivor的10%只有一个Survivor空间即10%的新生代是会被“浪费”的。 3.3.4 标记-整理算法 针对老年代对象的存亡特征1974年Edward Lueders提出了另外一种有针对性的“标记-整理”Mark-Compact算法其中的标记过程仍然与“标记-清除”算法一样但后续步骤不是直接对可回收对象进行清理而是让所有存活的对象都向内存空间一端移动然后直接清理掉边界以外的内存。 3.5 经典垃圾收集器 下图为HotSpot虚拟机的垃圾收集器。 3.5.1 Serial收集器 在它进行垃圾收集时必须暂停其他所有工作线程直到它收集结束。 3.5.2 ParNew收集器 ParNew收集器实质上是Serial收集器的多线程并行版本。 在谈论垃圾收集器的上下文语境中并行和并发可以理解为 · 并行Parallel并行描述的是多条垃圾收集器线程之间的关系说明同一时间有多条这样的线程在协同工作通常默认此时用户线程是处于等待状态。 · 并发Concurrent并发描述的是垃圾收集器线程与用户线程之间的关系说明同一时间垃圾收集器线程与用户线程都在运行。由于用户线程并未被冻结所以程序仍然能响应服务请求但由于垃圾收集器线程占用了一部分系统资源此时应用程序的处理的吞吐量将受到一定影响。 3.5.3 Parallel Scavenge收集器 Parallel Scavenge收集器的特点是它的关注点与其他收集器不同CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量Throughput。 3.5.4 Serial Old收集器 Serial Old是Serial收集器的老年代版本它同样是一个单线程收集器使用标记-整理算法。这个收集器的主要意义也是供客户端模式下的HotSpot虚拟机使用。 3.5.5 Parallel Old收集器 Parallel Old是Parallel Scavenge收集器的老年代版本支持多线程并发收集基于标记-整理算法实现。 3.5.6 CMS收集器 CMSConcurrent Mark Sweep收集器是一种以获取最短回收停顿时间为目标的收集器。 从名字包含“Mark Sweep”上就可以看出CMS收集器是基于标记-清除算法实现的它的运作过程相对于前面几种收集器来说要更复杂一些整个过程分为四个步骤包括 1初始标记CMS initial mark 2并发标记CMS concurrent mark 3重新标记CMS remark 4并发清除CMS concurrent sweep 3.5.7 Garbage First收集器 Garbage First简称G1收集器是垃圾收集器技术发展历史上的里程碑式的成果它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。 JDK 9发布之日G1宣告取代Parallel Scavenge加Parallel Old组合成为服务端模式下的默认垃圾收集器而CMS则沦落至被声明为不推荐使用Deprecate的收集器。 在G1收集器出现之前的所有其他收集器包括CMS在内垃圾收集的目标范围要么是整个新生代Minor GC要么就是整个老年代Major GC再要么就是整个Java堆Full GC。而G1跳出了这个樊笼它可以面向堆内存任何部分来组成回收集Collection Set一般简称CSet进行回收衡量标准不再是它属于哪个分代而是哪块内存中存放的垃圾数量最多回收收益最大这就是G1收集器的Mixed GC模式。 G1开创的基于Region的堆内存布局是它能够实现这个目标的关键。虽然G1也仍是遵循分代收集理论设计的但其堆内存的布局与其他收集器有非常明显的差异G1不再坚持固定大小以及固定数量的分代区域划分而是把连续的Java堆划分为多个大小相等的独立区域Region每一个Region都可以根据需要扮演新生代的Eden空间、Survivor空间或者老年代空间。 Region中还有一类特殊的Humongous区域专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象。每个Region的大小可以通过参数-XXG1HeapRegionSize设定取值范围为1MB32MB且应为2的N次幂。而对于那些超过了整个Region容量的超级大对象将会被存放在N个连续的Humongous Region之中G1的大多数行为都把Humongous Region作为老年代的一部分来进行看待。 如果我们不去计算用户线程运行过程中的动作如使用写屏障维护记忆集的操作G1收集器的运作过程大致可划分为以下四个步骤 · 初始标记 Initial Marking仅仅只是标记一下GC Roots能直接关联到的对象并且修改TAMS指针的值让下一阶段用户线程并发运行时能正确地在可用的Region中分配新对象。这个阶段需要停顿线程但耗时很短而且是借用进行Minor GC的时候同步完成的所以G1收集器在这个阶段实际并没有额外的停顿。 · 并发标记 Concurrent Marking从GC Root开始对堆中对象进行可达性分析递归扫描整个堆里的对象图找出要回收的对象这阶段耗时较长但可与用户程序并发执行。当对象图扫描完成以后还要重新处理SATB记录下的在并发时有引用变动的对象。 · 最终标记 Final Marking对用户线程做另一个短暂的暂停用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录。 · 筛选回收 Live Data Counting and Evacuation负责更新Region的统计数据对各个Region的回收价值和成本进行排序根据用户所期望的停顿时间来制定回收计划可以自由选择任意多个Region构成回收集然后把决定回收的那一部分Region的存活对象复制到空的Region中再清理掉整个旧Region的全部空间。这里的操作涉及存活对象的移动是必须暂停用户线程由多条收集器线程并行完成的。 从上述阶段的描述可以看出G1收集器除了并发标记外其余阶段也是要完全暂停用户线程的换言之它并非纯粹地追求低延迟。 3.6 低延迟垃圾收集器 衡量垃圾收集器的三项最重要的指标是内存占用Footprint、吞吐量Throughput和延迟Latency三者共同构成了一个“不可能三角”。三者总体的表现会随技术进步而越来越好但是要在这三个方面同时具有卓越表现的“完美”收集器是极其困难甚至是不可能的一款优秀的收集器通常最多可以同时达成其中的两项。 3.6.1 Shenandoah收集器 Shenandoah相比起G1有什么改进呢虽然Shenandoah也是使用基于Region的堆内存布局同样有着用于存放大对象的Humongous Region默认的回收策略也同样是优先处理回收价值最大的Region……但在管理堆内存方面它与G1至少有三个明显的不同之处最重要的当然是支持并发的整理算法G1的回收阶段是可以多线程并行的但却不能与用户线程并发。其次Shenandoah目前是默认不使用分代收集的换言之不会有专门的新生代Region或者老年代Region的存在没有实现分代并不是说分代对Shenandoah没有价值这更多是出于性价比的权衡基于工作量上的考虑而将其放到优先级较低的位置上。最后Shenandoah摒弃了在G1中耗费大量内存和计算资源去维护的记忆集改用名为“连接矩阵”Connection Matrix的全局数据结构来记录跨Region的引用关系降低了处理跨代指针时的记忆集维护消耗也降低了伪共享问题的发生概率。 3.6.2 ZGC收集器 ZGC和Shenandoah的目标是高度相似的都希望在尽可能对吞吐量影响不太大的前提下实现在任意堆内存大小下都可以把垃圾收集的停顿时间限制在十毫秒以内的低延迟。 给ZGC下一个这样的定义来概括它的主要特征ZGC收集器是一款基于Region内存布局的暂时不设分代的使用了读屏障、染色指针和内存多重映射等技术来实现可并发的标记-整理算法的以低延迟为首要目标的一款垃圾收集器。 后记 下面截图是笔者阅读本书的记录多年以后回看会有不同的感触。
http://www.dnsts.com.cn/news/5460.html

相关文章:

  • 专做充电器的网站互联网保险案例
  • wordpress子站点打不开网站百度文库
  • 站长推荐网站网站数据链接怎么做
  • 米拓cms建站系统哪家公司设计网站好
  • 2018年主流网站开发语言app开发公司价格表
  • 怎么做网站公众号做英语阅读的网站
  • 制作一个网站一般先要明确浦项建设(中国)有限公司网站
  • 网站做熊掌号码南京润盛建设集团有限公司网站
  • 云南网站推广的目的wordpress插件升级
  • 哪个网站做h5比较好看网站后台设计教程视频
  • 电子商务网站建设 考卷开源php cms
  • 官方网站的作用wordpress模板仿新版虎嗅huxiu-new主题
  • 苏州正规做网站公司济南响应式网站开发
  • 0基础学网站开发网站备案 法人
  • 网站子站怎么建设企业网站排行榜
  • wordpress 仿煎蛋网站关键词搜索排名优化
  • 做网站去什么公司咸鱼app引导页面设计模板
  • 湖北省建设交易协会网站硬件工程师需要学哪些
  • 网站关键词seo费用wordpress 表格处理
  • 2W网站建设的作用wordpress post link
  • 制作网站主题360建筑网一级消防工程师招聘
  • 网站dns服务360建筑网上怎么删除投递信息
  • 重庆专业网站建设首页排名微信管理平台
  • 网站建设分金手指排名十二肥城网站建设广州外地车牌
  • 网站建设远程培训淘宝流量网站
  • 莒南做网站网站海外推广平台
  • 哪个公司网站建设好韩国怎么出线
  • 一个网站如何做盈利贡井移动网站建设
  • 网站建设潮州wordpress 负载
  • php网站开发工程师任职要求新开网站