jvm的GC分代收集算法及jvm配置说明

[漏洞挖掘与防护] 03.漏洞利用之WinRAR安全缺陷复现(CVE-2018-20250)及软件自启动分析 上一篇文章将详细介绍MS08-067远程代码执行漏洞(CVE-2008-4250)及防御过程,它是Windows Server服务RPC请求缓冲区溢出漏洞,利用445端口,并通过Metasploit工具获取shell及进行深入的操作。这篇文章将详细讲解WinRAR漏洞(CVE-2018-20250),并复现了该漏洞和讲解了恶意软件自启动劫持原理。基础性文章,希望对入门的同学有帮助。 阅读详情

官方文献
https://docs.oracle.com/javase/8/
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/
https://docs.oracle.com/javase/specs/index.html

 

 

摘要

当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。方法区永久代,回收方法同老年代。

对象分类

分代搜集算法是针对对象的不同特性,而使用适合的算法,这里面并没有实际上的新算法产生。与其说分代搜集算法是第四个算法,不如说它是对前三个算法的实际应用。 
首先我们来探讨一下对象的不同特性,接下来和各位来一起给这些对象选择GC算法。 
内存中的对象按照生命周期的长短大致可以分为三种,以下命名均为个人的命名。 
1、夭折对象(新生代):朝生夕灭的对象,通俗点讲就是活不了多久就得死的对象。 
例子:某一个方法的局域变量、循环内的临时变量等等。 
2、老不死对象(老年代):这类对象一般活的比较久,岁数很大还不死,但归根结底,老不死对象也几乎早晚要死的,但也只是几乎而已。 
例子:缓存对象、数据库连接对象、单例对象(单例模式)等等。 
3、不灭对象(永久代):此类对象一般一旦出生就几乎不死了,它们几乎会一直永生不灭,记得,只是几乎不灭而已。 
例子:String池中的对象(享元模式)、加载过的类信息等等。

对象对应的内存区域

还记得前面介绍内存管理时,JVM对内存的划分吗? 
我们将上面三种对象对应到内存区域当中,就是夭折对象和老不死对象都在JAVA堆,而不灭对象在方法区。 
之前的一章中我们就已经说过,对于JAVA堆,JVM规范要求必须实现GC,因而对于夭折对象和老不死对象来说,死几乎是必然的结局,但也只是几乎,还是难免会有一些对象会一直存活到应用结束。然而JVM规范对方法区的GC并不做要求,所以假设一个JVM实现没有对方法区实现GC,那么不灭对象就是真的不灭对象了。 
由于不灭对象的生命周期过长,因此分代搜集算法就是针对的JAVA堆而设计的,也就是针对夭折对象和老不死对象。

JAVA堆的对象回收(夭折对象和老不死对象)

有了以上分析,我们来看看分代搜集算法如何处理JAVA堆的内存回收的,也就是夭折对象与老不死对象的回收。 
夭折对象:这类对象朝生夕灭,存活时间短,还记得复制算法的使用要求吗?那就是对象存活率不能太高,因此夭折对象是最适合使用复制算法的。 
小疑问:50%内存的浪费怎么办? 
答疑:因为夭折对象一般存活率较低,因此可以不使用50%的内存作为空闲,一般的,复制算法:使用两块10%的内存作为空闲和活动区间,而另外80%的内存,则是用来给新建对象分配内存的。一旦发生GC,将10%的活动区间与另外80%中存活的对象转移到10%的空闲区间,接下来,将之前90%的内存全部释放,以此类推。 
GC流程: 


这里写图片描述

 

 


这里写图片描述

 

图中标注了三个区域中在各个阶段,各自内存的情况。相信看着图,它的GC流程已经不难理解了。 
第一点是使用这样的方式,我们只浪费了10%的内存,这个是可以接受的,因为我们换来了内存的整齐排列与GC速度。第二点是,这个策略的前提是,每次存活的对象占用的内存不能超过这10%的大小,一旦超过,多出的对象将无法复制。 
为了解决上面的意外情况,也就是存活对象占用的内存太大时的情况,高手们将JAVA堆分成两部分来处理,上述三个区域则是第一部分,称为新生代或者年轻代。而余下的一部分,专门存放老不死对象的则称为年老代。 
是不是很贴切的名字呢?下面我们看看老不死对象的处理方式。 
老不死对象:这一类对象存活率非常高,因为它们大多是从新生代转过来的。就像人一样,活的年月久了,就变成老不死了。 
通常情况下,以下两种情况发生的时候,对象会从新生代区域转到年老带区域。 
1. 在新生代里的每一个对象,都会有一个年龄,当这些对象的年龄到达一定程度时(年龄就是熬过的GC次数,每次GC如果对象存活下来,则年龄加1),则会被转到年老代,而这个转入年老代的年龄值,一般在JVM中是可以设置的。 
2. 在新生代存活对象占用的内存超过10%时,则多余的对象会放入年老代。这种时候,年老代就是新生代的“备用仓库”。 
针对老不死对象的特性,显然不再适合使用复制算法,因为它的存活率太高,而且不要忘了,如果年老代再使用复制算法,它可是没有备用仓库的。因此一般针对老不死对象只能采用标记/整理或者标记/清除算法。 
以上两种情况已经解决了GC的大部分问题,因为JAVA堆是GC的主要关注对象,而以上也已经包含了分代搜集算法的全部内容,接下来对于不灭对象的回收,已经不属于分代搜集算法的内容。

方法区的对象回收(不灭对象)

不灭对象存在于方法区,在我们常用的hotspot虚拟机(JDK默认的JVM)中,方法区也被亲切的称为永久代,又是一个很贴切的名字不是吗? 
其实在很久很久以前,是不存在永久代的。当时永久代与年老代都存放在一起,里面包含了JAVA类的实例信息以及类信息。但是后来发现,对于类信息的卸载几乎很少发生,因此便将二者分离开来。幸运的是,这样做确实提高了不少性能。于是永久代便被拆分出来了。 
这一部分区域的GC与年老代采用相似的方法,由于都没有“备用仓库”,二者都是只能使用标记/清除和标记/整理算法。

回收的时机

JVM在进行GC时,并非每次都对上面三个内存区域一起回收的,大部分时候回收的都是指新生代。因此GC按照回收的区域又分了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC),它们所针对的区域如下。 
普通GC(minor GC):只针对新生代区域的GC。 
全局GC(major GC or Full GC):针对所有分代区域(新生代、年老代)的GC。 
由于年老代与永久代相对来说GC效果不好,而且二者的内存使用增长速度也慢,因此一般情况下,需要经过好几次普通GC,才会触发一次全局GC。

Java内存分配机制

这里所说的内存分配,主要指的是在堆上的分配,一般的,对象的内存分配都是在堆上进行,但现代技术也支持将对象拆成标量类型(标量类型即原子类型,表示单个值,可以是基本类型或String等),然后在栈上分配,在栈上分配的很少见,我们这里不考虑。 
 Java内存分配和回收的机制概括的说,就是:分代分配,分代回收。对象将根据存活的时间被分为:年轻代(Young Generation)、年老代(Old Generation)、永久代(Permanent Generation,也就是方法区)。如下图 
  这里写图片描述 
     
  年轻代(Young Generation):对象被创建时,内存的分配首先发生在年轻代(大对象可以直接 被创建在年老代),大部分的对象在创建后很快就不再使用,因此很快变得不可达,于是被年轻代的GC机制清理掉(IBM的研究表明,98%的对象都是很快消 亡的),这个GC机制被称为Minor GC或叫Young GC。注意,Minor GC并不代表年轻代内存不足,它事实上只表示在Eden区上的GC。

  年轻代上的内存分配是这样的,年轻代可以分为3个区域:Eden区(伊甸园,亚当和夏娃偷吃禁果生娃娃的地方,用来表示内存首次分配的区域,再贴切不过)和两个存活区(Survivor 0 、Survivor 1)。内存分配过程为 
  这里写图片描述

绝大多数刚创建的对象会被分配在Eden区,其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快; 
当Eden区满的时候,执行Minor GC,将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的); 
此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0; 
当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。 
当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。 
  从上面的过程可以看出,Eden区是连续的空间,且Survivor总有一个为空。经过一次GC和复制,一个Survivor中保存着当前还活 着的对象,而Eden区和另一个Survivor区的内容都不再需要了,可以直接清空,到下一次GC时,两个Survivor的角色再互换。因此,这种方 式分配内存和清理内存的效率都极高,这种垃圾回收的方式就是著名的“停止-复制(Stop-and-copy)”清理法(将Eden区和一个Survivor中仍然存活的对象拷贝到另一个Survivor中),这不代表着停止复制清理法很高效,其实,它也只在这种情况下高效,如果在老年代采用停止复制,则挺悲剧的。

  在Eden区,HotSpot虚拟机使用了两种技术来加快内存分配。分别是bump-the-pointer和TLAB(Thread- Local Allocation Buffers),这两种技术的做法分别是:由于Eden区是连续的,因此bump-the-pointer技术的核心就是跟踪最后创建的一个对象,在对 象创建时,只需要检查最后一个对象后面是否有足够的内存即可,从而大大加快内存分配速度;而对于TLAB技术是对于多线程而言的,将Eden区分为若干 段,每个线程使用独立的一段,避免相互影响。TLAB结合bump-the-pointer技术,将保证每个线程都使用Eden区的一段,并快速的分配内 存。 
  年老代(Old Generation):对象如果在年轻代存活了足够长的时间而没有被清理掉(即在几次 Young GC后存活了下来),则会被复制到年老代,年老代的空间一般比年轻代大,能存放更多的对象,在年老代上发生的GC次数也比年轻代少。当年老代内存不足时, 将执行Major GC,也叫 Full GC。   
  可以使用-XX:+UseAdaptiveSizePolicy开关来控制是否采用动态控制策略,如果动态控制,则动态调整Java堆中各个区域的大小以及进入老年代的年龄。 
  如果对象比较大(比如长字符串或大数组),Young空间不足,则大对象会直接分配到老年代上(大对象可能触发提前GC,应少用,更应避免使用短命的大对象)。用-XX:PretenureSizeThreshold来控制直接升入老年代的对象大小,大于这个值的对象会直接分配在老年代上。 
 可能存在年老代对象引用新生代对象的情况,如果需要执行Young GC,则可能需要查询整个老年代以确定是否可以清理回收,这显然是低效的。解决的方法是,年老代中维护一个512 byte的块——”card table“,所有老年代对象引用新生代对象的记录都记录在这里。Young GC时,只要查这里即可,不用再去查全部老年代,因此性能大大提高。

Java GC机制

年轻代:

  事实上,在上一节,已经介绍了新生代的主要垃圾回收方法,在新生代中,使用“停止-复制”算法进行清理,将新生代内存分为2部分,1部分 Eden区较大,1部分Survivor比较小,并被划分为两个等量的部分。每次进行清理时,将Eden区和一个Survivor中仍然存活的对象拷贝到 另一个Survivor中,然后清理掉Eden和刚才的Survivor。 
  这里也可以发现,停止复制算法中,用来复制的两部分并不总是相等的(传统的停止复制算法两部分内存相等,但新生代中使用1个大的Eden区和2个小的Survivor区来避免这个问题)

  由于绝大部分的对象都是短命的,甚至存活不到Survivor中,所以,Eden区与Survivor的比例较大,HotSpot默认是 8:1,即分别占新生代的80%,10%,10%。如果一次回收中,Survivor+Eden中存活下来的内存超过了10%,则需要将一部分对象分配到 老年代。用-XX:SurvivorRatio参数来配置Eden区域Survivor区的容量比值,默认是8,代表Eden:Survivor1:Survivor2=8:1:1.

老年代:

老年代存储的对象比年轻代多得多,而且不乏大对象,对老年代进行内存清理时,如果使用停止-复制算法,则相当低效。一般,老年代用的算法是标记-整理算法,即:标记出仍然存活的对象(存在引用的),将所有存活的对象向一端移动,以保证内存的连续。 
在发生Minor GC时,虚拟机会检查每次晋升进入老年代的大小是否大于老年代的剩余空间大小,如果大于,则直接触发一次Full GC,否则,就查看是否设 置了-XX:+HandlePromotionFailure(允许担保失败),如果允许,则只会进行MinorGC,此时可以容忍内存分配失败;如果不 允许,则仍然进行Full GC(这代表着如果设置-XX:+Handle PromotionFailure,则触发MinorGC就会同时触发Full GC,哪怕老年代还有很多内存,所以,最好不要这样做)。

方法区(永久代):

  永久代的回收有两种:常量池中的常量,无用的类信息,常量的回收很简单,没有引用了就可以被回收。对于无用的类进行回收,必须保证3点: 
类的所有实例都已经被回收 
加载类的ClassLoader已经被回收 
类对象的Class对象没有被引用(即没有通过反射引用该类的地方) 
永久代的回收并不是必须的,可以通过参数来设置是否对类进行回收。HotSpot提供-Xnoclassgc进行控制 
使用-verbose,-XX:+TraceClassLoading、-XX:+TraceClassUnLoading可以查看类加载和卸载信息 
-verbose、-XX:+TraceClassLoading可以在Product版HotSpot中使用; 
-XX:+TraceClassUnLoading需要fastdebug版HotSpot支持 
垃圾收集器

参数内容
-Xms初始堆大小。如:-Xms256m
-Xmx最大堆大小。如:-Xmx512m
-Xmn新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%
-XssJDK1.5+ 每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的。
-XX:NewRatio新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3
-XX:SurvivorRatio新生代中 Eden(8) 与 Survivor(1+1) 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10
-XX:PermSize永久代(方法区)的初始大小
-XX:MaxPermSize永久代(方法区)的最大值
-XX:+PrintGCDetails打印 GC 信息
-XX:+HeapDumpOnOutOfMemoryError让虚拟机在发生内存溢出时 Dump 出当前的内存堆转储快照,以便分析用
 -XX:HeapDumpPath自定义指定oom时dump文件存储路径,不配置时保存到默认路径

垃圾收集器

在GC机制中,起重要作用的是垃圾收集器,垃圾收集器是GC的具体实现,Java虚拟机规范中对于垃圾收集器没有任何规定,所以不同厂商实现的垃圾 收集器各不相同,HotSpot 1.6版使用的垃圾收集器如下图(图来源于《深入理解Java虚拟机:JVM高级特效与最佳实现》,图中两个收集器之间有连线,说明它们可以配合使用): 
这里写图片描述

在介绍垃圾收集器之前,需要明确一点,就是在新生代采用的停止复制算法中,“停 止(Stop-the-world)”的意义是在回收内存时,需要暂停其他所 有线程的执行。这个是很低效的,现在的各种新生代收集器越来越优化这一点,但仍然只是将停止的时间变短,并未彻底取消停止。

Serial收集器:新生代收集器,使用停止复制算法,使用一个线程进行GC,其它工作线程暂停。使用-XX:+UseSerialGC可以使用Serial+Serial Old模式运行进行内存回收(这也是虚拟机在Client模式下运行的默认值) 
ParNew收集器:新生代收集器,使用停止复制算法,Serial收集器的多线程版,用多个线程进行GC,其它工作线程暂停,关注缩短垃圾收集时间。使用-XX:+UseParNewGC开关来控制使用ParNew+Serial Old收集器组合收集内存;使用-XX:ParallelGCThreads来设置执行内存回收的线程数。 
Parallel Scavenge 收集器:新生代收集器,使用停止复制算法,关注CPU吞吐量,即运行用户代码的时间/总时间,比如:JVM运行100分钟,其中运行用户代码99分钟,垃 圾收集1分钟,则吞吐量是99%,这种收集器能最高效率的利用CPU,适合运行后台运算(关注缩短垃圾收集时间的收集器,如CMS,等待时间很少,所以适 合用户交互,提高用户体验)。使用-XX:+UseParallelGC开关控制使用 Parallel Scavenge+Serial Old收集器组合回收垃圾(这也是在Server模式下的默认值);使用-XX:GCTimeRatio来设置用户执行时间占总时间的比例,默认99,即 1%的时间用来进行垃圾回收。使用-XX:MaxGCPauseMillis设置GC的最大停顿时间(这个参数只对Parallel Scavenge有效) 
Serial Old收集器:老年代收集器,单线程收集器,使用标记整理(整理的方法是Sweep(清理)和Compact(压缩),清理是将废弃的对象干掉,只留幸存 的对象,压缩是将移动对象,将空间填满保证内存分为2块,一块全是对象,一块空闲)算法,使用单线程进行GC,其它工作线程暂停(注意,在老年代中进行标 记整理算法清理,也需要暂停其它线程),在JDK1.5之前,Serial Old收集器与ParallelScavenge搭配使用。 
Parallel Old收集器:老年代收集器,多线程,多线程机制与Parallel Scavenge差不错,使用标记整理(与Serial Old不同,这里的整理是Summary(汇总)和Compact(压缩),汇总的意思就是将幸存的对象复制到预先准备好的区域,而不是像Sweep(清 理)那样清理废弃的对象)算法,在Parallel Old执行时,仍然需要暂停其它线程。Parallel Old在多核计算中很有用。Parallel Old出现后(JDK 1.6),与Parallel Scavenge配合有很好的效果,充分体现Parallel Scavenge收集器吞吐量优先的效果。使用-XX:+UseParallelOldGC开关控制使用Parallel Scavenge +Parallel Old组合收集器进行收集。 
CMS(Concurrent Mark Sweep)收集器:老年代收集器,致力于获取最短回收停顿时间,使用标记清除算法,多线程,优点是并发收集(用户线程可以和GC线程同时工作),停顿小。使用-XX:+UseConcMarkSweepGC进行ParNew+CMS+Serial Old进行内存回收,优先使用ParNew+CMS(原因见后面),当用户线程内存不足时,采用备用方案Serial Old收集。 
CMS收集的方法是:先3次标记,再1次清除,3次标记中前两次是初始标记和重新标记(此时仍然需要停止(stop the world)), 初始标记(Initial Remark)是标记GC Roots能关联到的对象(即有引用的对象),停顿时间很短;并发标记(Concurrent remark)是执行GC Roots查找引用的过程,不需要用户线程停顿;重新标记(Remark)是在初始标记和并发标记期间,有标记变动的那部分仍需要标记,所以加上这一部分 标记的过程,停顿时间比并发标记小得多,但比初始标记稍长。在完成标记之后,就开始并发清除,不需要用户线程停顿。 
所以在CMS清理过程中,只有初始标记和重新标记需要短暂停顿,并发标记和并发清除都不需要暂停用户线程,因此效率很高,很适合高交互的场合。 
CMS也有缺点,它需要消耗额外的CPU和内存资源,在CPU和内存资源紧张,CPU较少时,会加重系统负担(CMS默认启动线程数为(CPU数量+3)/4)。 
另外,在并发收集过程中,用户线程仍然在运行,仍然产生内存垃圾,所以可能产生“浮动垃圾”,本次无法清理,只能下一次Full GC才清理,因此在GC期间,需要预留足够的内存给用户线程使用。所以使用CMS的收集器并不是老年代满了才触发Full GC,而是在使用了一大半(默认68%,即2/3,使用-XX:CMSInitiatingOccupancyFraction来设置)的时候就要进行Full GC,如果用户线程消耗内存不是特别大,可以适当调高-XX:CMSInitiatingOccupancyFraction以降低GC次数,提高性能,如果预留的用户线程内存不够,则会触发Concurrent Mode Failure,此时,将触发备用方案:使用Serial Old 收集器进行收集,但这样停顿时间就长了,因此-XX:CMSInitiatingOccupancyFraction不宜设的过大。 
还有,CMS采用的是标记清除算法,会导致内存碎片的产生,可以使用-XX:+UseCMSCompactAtFullCollection来设置是否在Full GC之后进行碎片整理,用-XX:CMSFullGCsBeforeCompaction来设置在执行多少次不压缩的Full GC之后,来一次带压缩的Full GC。

G1收集器:在JDK1.7中正式发布,与现状的新生代、老年代概念有很大不同,目前使用较少,不做介绍。 
注意并发(Concurrent)和并行(Parallel)的区别: 

1. 并发是指用户线程与GC线程同时执行(不一定是并行,可能交替,但总体上是在同时执行的),不需要停顿用户线程(其实在CMS中用户线程还是需要停顿的,只是非常短,GC线程在另一个CPU上执行); 
2. 并行收集是指多个GC线程并行工作,但此时用户线程是暂停的; 
所以,Serial和Parallel收集器都是并行的,而CMS收集器是并发的.

参考: 
http://www.it165.net/pro/html/201501/32890.html 
http://blog.youkuaiyun.com/ochangwen/article/details/51407574 
http://blog.youkuaiyun.com/ochangwen/article/details/51407167 
http://www.cnblogs.com/hnrainll/archive/2013/11/06/3410042.html

【RT-DETR多模态融合改进】在前期、中期、中后期、后期多模态融合中添加P6大目标检测层,完整步骤及代码 主题: RT-DETR的多模态融合改进中增加P6大目标检测层方式: 分别在前期融合、中期融合、中-后期融合、后期融合中增加P6多模态融合检测层。内容: 包含融合方式详解以及完整配置步骤,开箱即用,一键运行。原始模型结构如下: 二、有效特征层对应的检测头类别 2.1 P3/8 - small检测头 原始模型中的对应的检测头主要用于检测相对较小的目标。其特征图大小相对较大,空间分辨率较高。 适合检测尺寸大概在到像素左右的目标。 2.2 P4/16 - medium检测头 这个检测头对应的经过了更多的下采样 阅读详情

相关推荐

vmware vsphere 证书过期告警处理方法

vSphere Clinet 管理页面出现“证书告警” ,检查证书未发现现有证书有过期现象

m0_51902127的博客 3639

【快速入门JVM】Java虚拟机规范之(分代收集算法)4大GC算法

  GC的作用范围是方法区和堆区,次数上频繁收集Young区、次数上频繁收集Old区、基本不动Perm区(特殊情况也会清除永久区)。   JVM在进行GC时,并非每次都对三个内存区域一起回收的,大部分时候回收的都是指新生代。 所以GC按照回收的区域又分了两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC)。   普通GC(minor GC):只...

林大侠 688

SmsForwarder v6.4.0 + Flask API 实战:5步搭建手机验证码自动化接收服务

本文详细介绍了如何利用SmsForwarder v6.4.0和Flask API构建企业级验证码自动化处理系统。通过5个关键步骤,包括系统架构设计、Android端配置、Flask服务端实现、企业级部署方案以及实战应用场景扩展,帮助开发者高效处理短信验证码,提升自动化测试和数据采集的工作效率。

weixin_30292745的博客 393

JVM学习-分代收集算法

1.分代回收算法概述 1.1.分代回收算法简介 我们在前面讲了三种垃圾回收算法,实际上,虚拟机结合这三种算法,让它们协同工作,具体的实现使用分代垃圾回收机制。 我们将堆内存区域划分为新生代和老年代。 新生代中又划分为伊甸园、幸存区From、幸存区To。 因为Java中有的对象需要长时间使用,长时间使用的对象,我们将之放在老年代中,而那些用完了就可以丢弃的对象,我们将之放在新生代中,这样我们就可以根据对象生命周期的不同特点进行不同的垃圾回收策略。老年代的垃圾回收很久才一次,新生代的垃圾回收则比较频繁。针对不

Java硬件工程师的博客 5479

CloudCompare如何进行二次开发?

CloudCompare源代码编译成功后,即可进行二次开发,可以通过修改源码或者制作插件实现二次开发。本文二次开发采用修改CloudCompare的源代码的方式,分别修改mainwindow.ui、mainwindow.h、mainwindow.cpp,实现扩展功能,克隆选中的点云。

【cacrle】的博客 5332

薄膜电容寿命预测全解析:从理论到实践,5步搞定可靠性评估

本文全面解析薄膜电容寿命预测的理论与实践,提供五步可靠性评估流程,涵盖温度应力、电压应力等关键因素分析,并分享提升寿命的实用技巧。特别适用于新能源、电动汽车等领域的设计工程师,帮助准确预测薄膜电容在实际工况下的使用寿命。

weixin_33712987的博客 433

GC回收算法

GC回收算法

Knight 1139

Zemax操作33--5倍激光扩束器

5倍扩束

lzy750750的博客 2933

JVM-垃圾回收理论、分代算法、垃圾收集器

为了解决跨代引用问题,提出了记忆集这个概念,记忆集是一个在新生代中使用的数据结构,它相当于是记录了一些指针的集合,指向了老年代中哪些对象存在跨代引用。字长精度:每个记录精确到一个字长,机器字长就是处理器的寻址位数,比如常见的 32 位或者 64 位处理器,这个精度决定了机器访问物理内存地址的指针长度,字中包含跨代指针;对象精度:每个记录精确到一个对象,该对象里含有跨代指针;卡精度:每个记录精确到一块内存区域,区域内含有跨代指针。

ALONG的博客 936

【YOLO系列】YOLOv8详解:模型结构、损失函数、训练方法及代码实现

YOLOv8是Ultralytics团队2023年推出的高效目标检测框架,在速度与精度平衡、多任务支持和易用性方面实现突破。模型采用改进的CSPDarknet主干网络、C2f模块和SPPF加速结构,结合PAN-FPN特征融合和解耦检测头设计,支持目标检测、实例分割和关键点检测任务。创新性地使用CIoU定位损失、Focal Loss置信度损失和动态样本分配策略,显著提升检测性能。实验表明,YOLOv8较前代模型mAP提升5-10%,在TensorRT加速下可达1000FPS,提供5种尺寸灵活选择,成为实时目标

一碗白开水一 2779

Python爬虫实战:全自动采集银行理财产品收益率数据

本文通过Playwright动态爬虫技术,成功实现了对银行理财产品收益率数据的实时采集,并通过 Pandas 数据清洗、SQLite 存储、调度自动化等模块,构建了一个可扩展的银行理财数据抓取系统。理财非儿戏,数据做决策。掌握银行收益信息是我们迈向理性投资的第一步。希望这套工具对你有所帮助!

2201_76125261的博客 1156

【JVM】分代收集算法:提升Java垃圾回收效率

分代收集算法作为Java虚拟机垃圾回收的重要优化方式,通过对不同生命周期对象采用不同的回收策略,提高了垃圾回收的效率和性能。合理利用分代收集算法,可以优化Java应用程序的性能和稳定性,提升用户体验。

double222222的博客 1534

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JDK1.7及更低版本jvm的GC分代收集算法及jvm配置说明

这里的低版本指JDK1.5、1.6、1.7 摘要 当前商业虚拟机的垃圾收集都采用“分代收集”(Generational Collection)算法,这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把Java堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要...

第三眼的思绪 1389

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Java高阶私房菜:JVM分代收集算法介绍和各垃圾收集器原理分解

现在市面上充斥着许多对于JVM垃圾收集器教程,有零基础的,有专讲的 ... 这些教程或文章大都长篇大论的细扣字眼,内容繁多且没有重点,看过便会忘,本篇集结了9年老JAVA工作经验,专讲面试和工作中使用到的,一站式讲解,帮助你疏通学习脉络,少走弯路。

猫步轻移,以学求知。余于此方寸之地,如猫观鼠,细察技艺所得,思维所悟。灵思如猫之警觉,日积月累,终成智海; 2152

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

GC-分代收集器

十款GC收集器上图中共有十款GC收集器,它们可以根据回收时的属性分为分代和分区两种类型:分代收集器:Serial、ParNew、Parallel Scavenge、CMS、Serial Old(MSC)、Parallel Old分区收集器:G1、ZGC、ShenandoahGC收集器中的名词解释在GC收集器中存在一些经常出现的名词,这些名词也是在认识GC收集器之前不得不了解的,如:串行回收、并行回收、独占执行、并发执行、吞吐量、停顿时间、吞吐量优先、响应时间优先等。串行、并行与独占、并发。

weixin_43776652的博客 1267

JVM分代收集机制解析

在深入探讨Java虚拟机(JVM)的内存管理机制之前,让我们想象一个常见的场景:一个大型Web应用服务器,它需要处理成千上万的并发请求。随着用户数量的增加,服务器内存逐渐被各种对象占用,而其中许多对象在一段时间后已经不再被使用。如果这些无用对象不能被及时回收,内存占用将不断攀升,最终可能导致系统崩溃。这种情况下,JVM的分代收集机制就显得尤为重要。分代收集是JVM内存管理的一个重要知识点,它基于这样一个事实:不同类型的对象在内存中存活的时间差异很大。

我是Java程序员廖志伟,感谢朋友们的支持!不定期贡献一篇高品质、过万文字、图文并茂且附有视频解说、满载代码示例注释的良心之作,坚决杜绝粗制乱造。 1574

JVM(8)——详解分代收集算法

JVM 的分代收集算法不是一种具体的垃圾收集算法实现,而是一种指导思想和设计原则,是现代 JVM 垃圾收集器的基石。其核心思想源于对程序运行过程中对象生命周期分布的观察(即弱分代假说)。

2301_80652249的博客 1193

JVM--GC(分代收集算法)

GC(是jvm垃圾回收分代收集算法) 为什么是分代呢,因为他在每个代中采用的不同的算法; 堆的内存结构 总体来说: 次数上频繁收集Young区 次数上较少收集Old区 基本不动Perm区 gc的主要几种算法及分布 1.引用计数法:简单来说当这个引用计数为0时 清理 不过这种算法也存在缺陷:循环引用,比如你引用我,我引用你;这样的话两个都计数都不可能为0,都会成为常驻内存,引起堆爆 2:复制算法(Copying)(新生区的算法) 年轻代中使用的是Minor GC,这种GC算法采用的是复制算法(Co

qq_42296117的博客 2056

【JVM】GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析

【JVM】GC分代篇:分代GC器、CMS收集器、三色标记算法及YoungGC、FullGC日志剖析

blblccc 1261

JVM 垃圾回收算法-分代收集算法

分代收集算法是一种基于对象生命周期特征的垃圾回收策略。该算法观察到,大多数对象在创建后很快就会变得不可达(即“朝生夕灭”),而少部分对象则会存活较长时间。基于这一观察,分代收集算法将堆内存分为几个代,每个代用于存储生命周期不同的对象,并使用不同的垃圾回收策略来管理这些代。年轻代(Young Generation):用于存储新创建的对象。年轻代的垃圾回收频率高,但回收速度快。老年代(Old Generation):用于存储生命周期较长的对象。对象在年轻代经历多次垃圾回收后,会被提升到老年代。

Flying_Fish_roe的博客 1175

(七)JVM成神路之GC分代篇:分代GC器、CMS收集器及YoungGC、FullGC日志剖析

引言 在《GC基础篇》中曾谈到过分代以及分区回收的概念,但基础篇更多的是建立在GC的一些算法理论上进行高谈阔论,而本篇则重点会对于分代收集器的实现进行全面详解,其中会涵盖串行收集器、并行收集器、三色标记、SATB算法、GC执行过程、并发标记、CMS收集器等知识,本篇则偏重于分析GC机制的落地实现,也就是垃圾收集器(Garbage Collector)。 一、堆空间回顾与GC收集器概述 GC覆盖的范围有堆空间与元空间,而主要的作用范围则是堆空间,所以先简单回顾堆空间后,再对于GC中的一些概念进行阐述,有了这些

weixin_45101064的博客 1952

分代收集算法

分代收集算法是JVM垃圾回收的机制,其实是【简单了解常见的GC算法】的综合应用。JVM的堆中存在许多对象,根据这些对象的生命周期(存活时间)可以将内存分为几个部分,eg:堆上的新生代和老年代,方法区的永久代。每个部分使用不同的GC算法进行垃圾回收,这就是分代收集算法。 新生代 顾名思义,新生代指新建对象存放的地方。一般来说,新建对象存放在新生代中,eg:局部变量。java程序中,90%以上的对...

suchenbin的博客 1284

GC-分代收集算法

垃圾收集器:跟踪存活对象,回收其他垃圾。GC算法主要通过标记,复制,整理,清除来进行垃圾的回收。 标记:记录所有存活的对象,通过标记可达对象来进行区分。 垃圾收集的两种算法主要是:分代收集算法,分区收集算法。 分代收集算法 j这种算法将根据对象存活时间来区分,在JVM中分为新生代,老年代,永久代(在java 8之后取消永久代,变为元空间)。 新生代:每次进行垃圾收集都会发现大量垃圾,采用的是“标记-复制”算法。 在新生代中又分为Eden区、SurvivorFrom区、SurvivorTo区。 Eden:是内

weixin_46913652的博客 1010

《剑指JVM》——第14章——分代收集算法——垃圾回收相关算法5

🔥本篇概览:详细讲解了分代收集算法——垃圾回收相关算法5🌈⭕🔥

做一个善良的人,做好自己的事,如果愿意,再发一份光。 934

【JVM】- 分代、GC算法

一、分代 左图是运行时数据区逻辑图,右图是分代逻辑图,右图中上边部分是JDK1.8之前的,下图是JDK1.8之后的;两张图中相同颜色代表相同的区域。 从图中我们可以得出,新生代和老年代是属于堆的;在JDK1.8之前,方法区也称为老年代,JDK1.8之后,取消了老年代,取而代之的是元空间Meta Space,也即是1.8后,方法区的实现方式有老年代变为了元空间。 设计元空间的目的,一是规避...

Brooks Lv 1535

【GC 分代收集算法 VS 分区收集算法】

我是廖志伟,一名Java开发工程师、幕后大佬社区创始人、Java领域优质创作者、优快云博客专家。拥有多年一线研发经验,研究过各种常见框架及中间件的底层源码,对于大型分布式、微服务、三高架构(高性能、高并发、高可用)有过实践架构经验。

我是Java程序员廖志伟,感谢朋友们的支持! 1075
上一篇: promotion failed和concurrent mode failure
下一篇: springboot中配置tomcat的access log
低调的杉菜
博客等级 码龄15年 12粉丝 34原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值