- 浏览: 2189425 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (682)
- 软件思想 (7)
- Lucene(修真篇) (17)
- Lucene(仙界篇) (20)
- Lucene(神界篇) (11)
- Solr (48)
- Hadoop (77)
- Spark (38)
- Hbase (26)
- Hive (19)
- Pig (25)
- ELK (64)
- Zookeeper (12)
- JAVA (119)
- Linux (59)
- 多线程 (8)
- Nutch (5)
- JAVA EE (21)
- Oracle (7)
- Python (32)
- Xml (5)
- Gson (1)
- Cygwin (1)
- JavaScript (4)
- MySQL (9)
- Lucene/Solr(转) (5)
- 缓存 (2)
- Github/Git (1)
- 开源爬虫 (1)
- Hadoop运维 (7)
- shell命令 (9)
- 生活感悟 (42)
- shell编程 (23)
- Scala (11)
- MongoDB (3)
- docker (2)
- Nodejs (3)
- Neo4j (5)
- storm (3)
- opencv (1)
最新评论
-
qindongliang1922:
粟谷_sugu 写道不太理解“分词字段存储docvalue是没 ...
浅谈Lucene中的DocValues -
粟谷_sugu:
不太理解“分词字段存储docvalue是没有意义的”,这句话, ...
浅谈Lucene中的DocValues -
yin_bp:
高性能elasticsearch ORM开发库使用文档http ...
为什么说Elasticsearch搜索是近实时的? -
hackWang:
请问博主,有用solr做电商的搜索项目?
Solr中Group和Facet的用法 -
章司nana:
遇到的问题同楼上 为什么会返回null
Lucene4.3开发之第八步之渡劫初期(八)
一,判断对象存活算法
JVM如何判断对象可以回收了?
主要的算法有:
1,引用计数算法,当多一个地方引用此类时,引用计数加一,否则就减一,算法很简单,实现也比较简单
缺点:很难解决对象之间相互引用的问题
2,可达性分析算法,通过一系列GC Roots路径,从节点开始搜索,来判断整个引用链是否还有关系。
在java语言中,可作为GC Roots的对象包括下面几种:
虚拟机栈(栈帧中的本地变量表)中引用的对象。
方法区类静态属性引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI引用的对象。
二,垃圾收集算法
(1),标记-清除算法
分为标记和清楚2个节点,首先标记出所有的需要回收的对象,标记完成后统以回收,它是垃圾回收里面最基础的算法,下面其他的几个都是基于这个算法改进的,
缺点: 标记和清除两个过程效率都不高,另外清除后悔产生大量不连续的内存碎片,碎片太多会导致,分配大对象时,找不到连续内存,从而提前触发另一次垃圾垃圾收集动作
(2),复制算法
为了解决效率问题,一种叫做复制的算法出现了,它将可用内存按容量分为大小相等的两块,每次使用其中一个,当这一个内存用完了,就把存活的对象复制到另一块上面,然后把已使用过的内存空间一次性清理掉,这样就使得每次都对半个区内存进行回收,分配时也不用考虑内存碎片等问题,只要移动堆顶指针,按顺序分配即可,简单,高效。
缺点:将内存缩小为原来一半,比较浪费空间,现在主流的商业虚拟机,基本都采用这种算法,来回收新生代。
(3),标记-整理算法
复制收集算法在对象存活率较多的时候,要进行较多的复制操作,效率将会变低,如果不想浪费一半的空间,就需要有额外的内存分配担保,应对100%对象都存活的极端情况,所以在老年代里面不能直接选用这种算法,根据老年代的特点,有人提出了另外一种的算法,标记-整理,过程仍与标记-清除一样,但是后续步骤不是直接回收,而是让所有存活对象,都向一端移动,然后清理掉其他的边界外的内存,避免了空间碎片的出现。
(4),分代收集算法
当前的商业虚拟机都采用分代收集的算法,将对象存活周期划分为几块,一般是把Java堆划分为新生代和老年代,这样就可以根据各个年代的特点,采用最适当的收集算法,在新生代中,每次垃圾收集时都有大批对象死去,只有少量存活,那就选复制算法,只需要付出少量存活对象的复制成本就可以完成收集,而老年代中因为对象存活率高,没有额外空间对它进行分配担保,就必须使用标记-清除或标记-整理算法来回收。
下面,来看下7种用于不同分代垃圾收集器,如下图所示:(注意连线部分代表,两种收集器,可以配合使用,)
1,Serial收集器
serial收集器,是最基本,发展历史最悠久的收集器,曾经在JDK1.3之前,是虚拟机新生代的唯一收集器,这个收集器是单线程的,简单而高效,对于Client的桌面模式是一个不错的选择。
2,ParNew收集器
ParNew收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,它的控制参数包含serial所有的控制参数,正是因为它的多线程收集优势,所以是许多运行在Server模式下的虚拟机中首选的新生代收集器,,其中一个与性能无关的重要原因是,除了Serial收集器外,目前只有它能与CMS老年代收集器配合工作,注意,单核CPU下,建议还是使用Serial收集器。
下面解释下并发和并行的收集器的区别:
并行(Parallel):指多条垃圾收集线程并行工作,但此时其他所有的用户线程都处于等待状态
并发(Concurrent):指用户线程与与垃圾收集线程同时运行,但一定是并行,可能会交替执行,用户程序在继续,而垃圾收集程序,运行在另一个CPU上
3,Parallel Scanvenge收集器
Parallel Scanvenge收集器是一个新生代收集器,他也是使用复制算法的收集器,又是并行的多线程收集器,它的关注点和其他的的收集不同,CMS等收集器关注点尽可能的缩短垃圾收集时用户线程的停顿时间,而Parallel Scanvenge收集器则是达到一个可控制的吞吐量,这是两种不同的应用场景。
停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验,特别是在搜索类电商中,而高吞吐量则可以高效率的利用cpu时间,尽快完成程序的计算任务,适合在后台运算,不需要太多的交互的任务,另外自适应调节策略也是Parallel Scanvenge收集器与ParNwe收集器的一个重要区别
4,Searial Old收集器
单线程的老年代的收集器,主要应用与Client模式下的虚拟机,如果放在Server模式下,还有两大用途,一作为CMS收集器的后备方案,在CMS失败时启用,另外一种是与Parallel Scavenge收集搭配使用。
5,Parallel Old收集器
Parallel Old收集器是Parallel Scavenge的老年代版本,使用多线程和标记-整理算法,在JDK1.6中才开始提供,在这之前,如果新生代选择了Parallel Scavenge收集器,老年代只能使用Serail old,Parallel Old收集器出现后,使组合方式变的更多了。
6,CMS收集器
CMS收集器是一种以获取最短回收停顿时间为目标的收集器,目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视响应速度,而散仙所在的搜索组更是注重系统交互响应时间,停顿时间越短,给用户带来更快更流畅的体验,CMS就非常符合这类应用的需求,CMS采用了标记-清除的算法实现,采取了并发的收集,举个例子,饭店的模式就非常类似,当所有的饭桌都做满人了,此时再来的客人,就需要等待别人吃完,这个时候,就是我们收集器里面的Full GCC触发的停顿,当峰值消退,饭店就可以一边吃饭,然后一边有人离去,然后一边有人进来,而不用等所有的客人都走完了,才重新进来,那样饭店不赔死了?
CMS的优点就是,并发收集,低停顿,但是它也有自身的缺点:
(1)CMS收集器会占用一部分的CPU资源,从而可能导致吞吐率下降
(2)CMS无法清理浮动垃圾,因为是并发处理,不断标记,不断清理,不断产生垃圾,CMS无法一次性清除掉垃圾,这部分被称为浮动垃圾,如果浮动垃圾产生的速度大于收集的速度,那么就有可能导致Concurrent Mode Failure失败,系统会临时采用Serial Old收集器,进行老年代收集,这样停顿时间就更长了。
(3)CMS的标记-清除算法,会产生大量的空间内存碎片,如果剩余的连续空间,不能够放下一个较大的对象实例时,将会触发Full Gc。
6,G1收集器
G1(JDK1.7的)收集器是当今收集器技术发展的最新成果之一,G1是一款面向服务端应用的垃圾收集器,HotSpot赋予它的使命是在未来较长时期内,可以替代掉JDK1.5中的CMS收集器
G1的特点:
(1)并行与并发:充分利用多CPU,多核环境环境下的硬件优势
(2)分代收集,采用不同的方式,收集新创建的,存活中,熬过多次的GC旧对象
(3)空间整合,采用复制拷贝垃圾回收算法,有效整理空间内存碎片
(4)可预测的停顿,建立可预测的停顿时间模型,在计划规定的时间内进行回收
最后再来看下GC日志的格式,先看下面的程序:
package com.test.gc; /* * -verbose:gc 、 * -XX:+PrintGCDetails -Xloggc:../gc.log * 或-XX:+PrintGCDetails -Xloggc:gc.log 将GC的日志log存储到指定文件中 * * * **/ public class GcTest { public Object instance=null; private static final int _1MB=1024*24; private byte[] bytes=new byte[2*_1MB]; public static void main(String[] args) { for(int i=0;i<20;i++){ GcTest g1=new GcTest(); GcTest g2=new GcTest(); g1.instance=g2; g2.instance=g1; g1=null; g2=null; } System.gc(); } }
GC的日志打印:
0.062: [GC [PSYoungGen: 2556K->520K(38080K)] 2556K->520K(125056K), 0.0007521 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 0.063: [Full GC (System) [PSYoungGen: 520K->0K(38080K)] [ParOldGen: 0K->465K(86976K)] 520K->465K(125056K) [PSPermGen: 2487K->2485K(21248K)], 0.0067204 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] Heap PSYoungGen total 38080K, used 1962K [0x00000000d58b0000, 0x00000000d8320000, 0x0000000000000000) eden space 32704K, 6% used [0x00000000d58b0000,0x00000000d5a9aa28,0x00000000d78a0000) from space 5376K, 0% used [0x00000000d78a0000,0x00000000d78a0000,0x00000000d7de0000) to space 5376K, 0% used [0x00000000d7de0000,0x00000000d7de0000,0x00000000d8320000) ParOldGen total 86976K, used 465K [0x0000000080a00000, 0x0000000085ef0000, 0x00000000d58b0000) object space 86976K, 0% used [0x0000000080a00000,0x0000000080a74470,0x0000000085ef0000) PSPermGen total 21248K, used 2496K [0x000000007b800000, 0x000000007ccc0000, 0x0000000080a00000) object space 21248K, 11% used [0x000000007b800000,0x000000007ba70088,0x000000007ccc0000)
格式详解,如下图所示:
Minor GC:
Full GC:
发表评论
-
记一次log4j不打印日志的踩坑记
2019-09-22 01:58 1590### 起因 前几天一个跑有java应用的生产集群(200多 ... -
在Java里面如何解决进退两难的jar包冲突问题?
2019-07-23 19:10 1255如上图所示: es api组件依赖guava18.0 ... -
如何轻松理解二叉树的深度遍历策略
2019-07-03 23:33 1152我们知道普通的线性数据结构如链表,数组等,遍历方式单一 ... -
为什么单线程Redis性能也很出色
2019-01-21 18:02 2224高性能的服务器,不一 ... -
如何将编程语言里面的字符串转成数字?
2019-01-11 23:23 2112将字符串转成数字在很 ... -
为什么Java里面String类是不可变的
2019-01-06 18:36 1684在Java里面String类型是不可变对象,这一点毫无疑问,那 ... -
关于Java里面volatile关键字的重排序
2019-01-04 18:49 1087Java里面volatile关键字主 ... -
多个线程如何轮流打印ABC特定的次数?
2018-12-11 20:42 6064之前的一篇文章,我给 ... -
聊聊Java里面的引用传递
2018-11-16 21:21 992长久以来,在Java语言里面一直有一个争论,就是Java语言到 ... -
理解计数排序算法的原理和实现
2018-10-11 10:03 2097计数排序(Counting sort) ... -
理解Java7和8里面HashMap+ConcurrentHashMap的扩容策略
2018-09-06 11:31 3394### 前言 理解HashMap和Con ... -
关于Java里面多线程同步的一些知识
2018-07-18 09:45 1111# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
Java单例模式之双检锁深入思考
2018-07-08 12:25 3298# Java单例模式之双检锁 ... -
关于Java里面多线程同步的一些知识
2018-07-08 12:23 1124# 关于Java里面多线程同步的一些知识 对于任何Java开 ... -
重新认识同步与异步,阻塞和非阻塞的概念
2018-07-06 14:30 1476# 重新认识同步与异步 ... -
线程的基本知识总结
2018-06-27 16:27 1063### (一)创建线程的方式 (1)实现Runnable接口 ... -
Java里面volatile关键字修饰引用变量的陷阱
2018-06-25 11:42 1390# Java里面volatile关键字修饰引用变量的陷阱 如 ... -
关于Java里面的字符串拼接,你了解多少?
2018-06-25 11:28 1376# 关于Java里面的字符串 ... -
深入理解Java内存模型的语义
2018-06-25 11:39 745### 前言 Java内存模型( ... -
如何证明Java多线程中的成员变量数据是互不可见的
2018-06-21 10:09 1509前面的几篇文章主要介绍了Java的内存模型,进程和线程的定义, ...
相关推荐
### 深入Java虚拟机JVM类加载学习笔记 #### 一、Classloader机制解析 在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及...
Java虚拟机(JVM)是Java程序的核心组成部分,它负责执行字节码并管理程序运行时的内存。本文主要探讨JVM的类加载机制,包括类加载、连接、初始化等关键过程,以及类的主动使用和被动使用的情况。 首先,我们要理解...
**JVM学习笔记(Java虚拟机)** Java虚拟机(JVM)是Java语言的核心组成部分,它是Java程序运行的平台,负责解释和执行字节码。深入理解JVM对于优化Java应用程序性能至关重要。本笔记将从以下几个方面详细介绍JVM:...
Java 虚拟机(JVM)自动内存管理机制 Java 虚拟机(JVM)自动内存管理机制是 Java 语言的一大特色,它使得 Java 程序员无需手动管理内存,从而提高了开发效率和程序稳定性。JVM 自动内存管理机制主要通过 JVM 的...
本文将深入探讨JVM中的访问控制器,主要基于“java之jvm学习笔记十一(访问控制器)-源码”这一主题,以及相关的源码分析。 首先,我们得了解Java的安全模型。Java安全模型基于一种称为安全管理器(SecurityManager)...
读书笔记:深入理解Java虚拟机JVM高级特性与最佳实践第3版学习笔记
读书笔记:深入理解Java虚拟机JVM高级特性与最佳实践第3版 周志明 学习笔记
### 学习深入理解Java虚拟机的前几章笔记 #### JVM内存模型 Java虚拟机(JVM)的内存模型主要分为两大类:线程共享区和线程私有区。 ##### 线程共享区 - **堆**:是所有线程共享的内存区域,在这里存放着对象实例...
虚拟机学习笔记 Java 虚拟机(JVM)是 Java 语言的 runtime 环境,负责加载、验证、执行 Java 字节码。以下是 JVM 相关知识点的总结。 1. 运行时数据区域 JVM 的运行时数据区域主要包括: * 堆(Heap):...
它采用了“一次编写,到处运行”的原则,即一次编写的程序可以在不同的操作系统上运行,这得益于Java虚拟机(JVM)的存在。JVM是Java的核心组成部分,它可以将Java代码解释成特定平台上的机器码,从而实现跨平台运行...
Java 虚拟机(JVM)是Java编程语言的核心组成部分,它允许Java代码在不同的操作系统上运行,实现了“一次编写,到处运行”的目标。JVM 是一个虚拟计算机,能够执行字节码(.class文件),这些字节码是Java源代码经过...
读书笔记:《深入理解Java虚拟机JVM高级特性与最佳实践第2版》学习笔记
这个“java之jvm学习笔记五(实践写自己的类装载器)”很可能是对这一主题的详细探讨。 类装载器在Java中的主要职责是动态加载类到JVM中。Java的类装载器分为三个基本层次:启动类装载器(Bootstrap ClassLoader)、...
### 学习笔记之Java虚拟机详解 #### 运行时数据区域概览 Java虚拟机(JVM)运行时数据区域主要包括以下几部分:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区以及运行时常量池。 1. **程序计数器**: -...
### Java分布式应用学习笔记02再谈JVM 在深入探讨Java虚拟机(JVM)时,我们再次聚焦于这个核心组件,它不仅是Java运行环境的心脏,也是构建分布式应用的关键技术之一。JVM作为Java语言的核心执行环境,其设计与...
尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机)学习笔记_NOTE_JVM
读书笔记:学习代码深入理解Java虚拟机JVM高级特性与最佳实践第3版 周志明
《JVM:深入理解Java虚拟机》是一本深入解析Java虚拟机工作原理和技术细节的经典书籍。这份学习笔记将涵盖JVM的关键概念、架构以及它如何影响Java程序的性能。我们将探讨以下几个方面: 1. **JVM概述** Java虚拟机...
除了上述提到的基础知识点外,《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》这本书籍还深入探讨了JVM的性能调优、并发编程、以及各种高级特性的具体应用。比如,对于性能调优,书中讲解了如何根据不同的...
它的设计目标是实现“一次编写,到处运行”,通过Java虚拟机(JVM)确保代码在不同操作系统上都能运行。Java语言的特点包括简洁性、面向对象、健壮性、安全性、高效性和可移植性。 【基本语法】 Java的基本语法包括...