JVM的基本介绍以及垃圾回收

目录
  • JVM java虚拟机
    • JVM
    • jvm主要组成部分及其作用
    • JVM Stack: jvm栈
  • 堆:
    • Jvm heap内存空间划分
  • Full GC
    • 一、OOM含义:
    • 二、监控GC命令
  • 总结

JVM java虚拟机

JVM

java虚拟机是一个可执行java字节码的虚拟机进程。Java虚拟机本质上就是一个程序,java源文件被编译成能被java虚拟机执行的字节码文件,当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令。Java语言的可移植性正是建立在Java虚拟机的基础上。任何平台只要装有针对于该平台的Java虚拟机,字节码文件(.class)就可以在该平台上运行。这就是“一次编译,多次运行”。

java文件,通过编译器变成了.class文件,接下来类加载器又将这些class文件加载到JVM中。其实可以一句话来解释,类的加载指的是将类的.class文件二进制数据读入到内存中,将其放在运行时数据区的方法区内,

然后在堆区创建一个 java.lang.Class对象,用来封装类在方法区内的数据结构。

jvm主要组成部分及其作用

我们常说的jvm的主要组成,指的是运行时数据区。但是,其他它还包括其他部分,执行引擎、本地接口、类加载子系统

jvm主要构成:方法区、Java堆、Java虚拟机栈、本地方法区、程序计数器等。

JAVA Heap:堆,放的是new的对象,数组,大数据的东西;运行时的数据

JVM Stack: jvm栈,控制方法怎么调度,控制应用程序怎么运行的

Native Method Stack:本地方法栈,本地的方法栈,调用本地服务

Method Area:方法区,放的是运行时的方法

其中方法区和堆是由所有线程共享,

而Java栈、本地方法区、程序计数器是线程私有。

我们常说的内存溢出,指的就是 java堆(Heap) 内存不够了。

JVM Stack jvm栈区,每启动个线程,jvm就为该线程分配一个栈区,线程调用方法时和方法返回时进行入栈和出栈的操作。

Native Stack 本地方法栈区,与jvm stack类似,不过此区域是为调用本地方法服务的

Java Heap java的所有对象实例,数组等。

程序计数寄存器 ,每个线程自己的计数寄存器,存储当前线程执行字节码的地址。

Program Counter Register:程序计数器:

每个线程在创建后,都会产生自己的程序计数器和栈帧。程序计数器用来存放执行指令的偏移量和行号指示器等。

线程执行或者恢复都要依赖程序计数器。程序计数器在各个线程之间互不影响。此区域也不会发生内存溢出异常,程序计数器是占用空间最小的内存区域,不会出现OOM。

主要记录当前线程正在执行的方法的指令地址。方便线程切换后能恢复到下一条指令的位置,如果是执行native方法,则该计数器为空。

程序计数器(后文简称PCR)有两个作用:

  • 字节码解释器通过改变PCR依次读取指令,实现代码的流程控制,如顺序执行、选择、循环、异常处理
  • 多线程情况下,PCR用于记录当前线程的执行位置,从而当线程被切换回来的时候,能够知道该线程上次运行到哪儿了。

JVM Stack: jvm栈

java虚拟机栈也叫线程栈

虚拟机栈包含:

1、局部变量表

2、动态连接

3、操作栈

4、方法返回地址

1、局部变量表

存放方法参数和局部变量

相对于类属性的变量准备阶段和初始化阶段,局部变量没有准备阶段,必需显式初始化。

如果是非静态方法,则在index[0]位置存储的是方法所属对象的实例引用,随后存储的是参数和局部变量。

2、动态连接

每个栈帧中包含一个在常量池中,对当前方法的引用。目的是支持方法调用过程的动态连接。

3、方法返回地址:

方法执行的时候,有两种退出情况:

正常退出

正常执行到任何方法的返回字节码指令,如RETURN、IRETURN等。

异常退出

无论何种,都将返回至方法当前被调用的位置。方法退出的过程相当于弹出当前栈帧。

3、操作栈

本地方法栈基本上等同于java虚拟机栈。

堆和栈是程序运行的关键,很有必要把他们癿关系说清楚。

栈是运行时的单位,而堆是存储的单位。

栈解决程序的运行问题,即程序如何执行,或者说如何处理数据;

堆解决的是数据存储的问题,即数 据怎么放、放在哪儿。

在 Java 中一个线程就会相应有一个线程栈与之对应,这点很容易理解,因为不同的线程执行逻辑有 所不同,因此需要一个独立的线程栈。

而堆则是所有线程共享的。

栈因为是运行单位,因此里面存储 的信息都是跟当前线程(或程序)相关信息的。包括局部变量、程序运行状态、方法返回值等等;而 堆只负责存储对象信息。

元数据区(Matespace):

包括:

常量池、类元信息、方法元信息

园区

JDK1.8之前叫持久代;1.8之后叫园区。

园区放的是方法常量

(以下非必需)

为什么要把堆和栈区分出来呢?栈中不是也可以存储数据吗?

第一,从软件设计的角度看,栈代表了处理逻辑,而堆代表了数据。这样分开,使得处理逻辑更为清 晰。分而治之的思想。这种隔离、模块化的思想在软件设计的方方面面都有体现。

第二,堆与栈的分离,使得堆中的内容可以被多个栈共享(也可以理解为多个线程访问同一个对象)。 这种共享的收益是很多的。一方面这种共享提供了一种有效的数据交互方式(如:共享内存),另一方 面,堆中的共享常量和缓存可以被所有栈访问,节省了空间。

第三,栈因为运行时的需要,比如保存系统运行的上下文,需要进行地址段的划分。由于栈只能向上 增长,因此就会限制住栈存储内容的能力。而堆不同,堆中的对象是可以根据需要动态增长的,因此 栈与堆的拆分,使得动态增长成为可能,相应栈中只需记录堆中的一个地址即可。

第四,面向对象就是堆与栈的完美结合。其实,面向对象方式的程序与以前结构化的程序在执行上没 有任何区别。但是,面向对象的引入,使得对待问题的思考方式发生了改变,而更接近于自然方式的思考。

当我们把对象拆开,你会发现,对象的属性其实就是数据,存放在堆中;而对象的行为(方法), 就是运行逻辑,放在栈中。

我们在编写对象的时候,其实即编写了数据结构,也编写了处理数据的逻辑。

在 Java 中,Main 函数就是栈的起始点,也是程序的起始点。

程序要运行总是有一个起点的。同 C 语言一样,java 中的 Main 就是那个起点。无论什么java 程序, 找到 main 就找到了程序执行的入口:

堆:

运行时的数据,也就是new的对象和一些数组。

运行时最大的数据,就在堆内。

Jvm heap内存空间划分

堆内(放的是对象,数组)=临时数据,用完就没啦

年轻代:eden +s1 +s0(eden:s1 :s0默认比例:8:1:1 )

老年代:(年轻代:老年代默认比例:1:2)

s0与s1大小相等,位置互换

堆外(放的是方法,类,常量)

Eden(伊甸园区):

所有新new的对象和数组,是在伊甸园区产生的,内存分配是在伊甸园区进行的。

在伊甸园区new 一个对象,如果这个对象被用到了,那么他的引用就+1。应用的越多,占内存越多。

当伊甸园区内存被占满时,就不能再new对象,程序依赖对象,所以程序也就不能运行。java应用程序为了能继续运行,就要干掉那些不被引用的对象,对这些不被引用的对象进行垃圾回收。

现代虚拟机一般使用的内存回收策略是分代收集,即把对象分为两代,新生代(年轻代)使用复制算法回收内存,老年代使用标志-整理算方法回收内存。

垃圾回收的时候,如何判断该对象是否可以被回收:

有2种算法

算法一:引用计数(已经被废弃了)

引用计数,对象被创建后,有个计数器。只要对象被引用,那么计数器就+1,再次被引用,就再+1,如果方法执行完成,对象不被引用了,计数器就-1。

当计数器为0时,该对象没有被引用,就可以被垃圾回收了。

引用计数算法,有一个弊端,就是在执行递归的时候,就没有办法计算了。

算法二:寻根判断

寻根判断,从对象的根结点开始去找,是否被引用,如果跟节点都没有引用,那么就是没有被引用。

被引用的对象,称为存活对象。

未被引用的对象,称为非存活对象。

当伊甸园区被占满时,触发GC(垃圾回收 Garbage Collection)。

GC分两步,第1步标记,对非存活对象进行标记。第2步清扫,将非存活对象从内存中干掉,释放内存,同时将存活的对象移到存活区中。

YGC

发生在年轻代。

在YGC之前,伊甸园区是满的,无法new对象,程序无法运行。

YGC之后,伊甸园区就空了,就可以继续new对象。

YGC整个流程:

第一次gc,,对存活的对象进行标记,然后将Eden区的存活对象,存活区S0

第二次gc,使用寻根判断的算法,对存活的对象进行标记,然后将Eden区的存活对象,移到存活区S0

步骤1:new的对象、数组,直接进入eden园区。

步骤2:eden园区满了,触发ygc,对【eden园区】的对象和数组进行标记(使用寻根判断的算法),清扫(将没有引用的对象干掉,被引用的移到其中一个存活区s0);

eden园区第二次满了,再次触发ygc,对【eden园区和存活区s0】的对象和数组进行标记,清扫将没有引用的干掉,被引用的对象和数组移到在另一个存活区s1(这里用的是复制算法)

步骤3:fgc,全gc,堆内存和持久代均gc。将没有的干掉,有用的放到老年代。

年轻代里面的两个存活区,大小相等,且同一时间只有一个存活区有对象,另一个存活区为空。gc之前,存活区s0有对象,s1为空,一次gc之后,s0为空,s1存放对象。

对象进入老年代原则:

大对象直接进入老年代长期存活的对象进入老年代动态年龄判断一次Young GC时数据放到存活区,但是存活区满了导致放不下去此时直接进入老年代(尽可能避免这种情况)

1、大对象直接进入老年代

在堆中分配的大对象直接挪到老年代

大对象是指需要大量连续内存空间的对象,例如很长的字符串以及数组。

虚拟机设置了一个-XX:PretenureSizeThreshold参数,有个默认值,令大于这个设置的对象直接在老年代分配,这个值是可以修改的。

目的就是为了防止大对象在Eden空间和Survivor空间来回大量复制,大对象很容易把伊甸园区占满,导致YGC频繁。

2、长期存活的对象进入老年代(伴随YGC产生的)

虚拟机给每个对象定义了一个对象年龄(Age)计数器,如果对象在Eden区出生并经过第一次YGC/Mintor GC后仍然存活,并且能被Survivor接纳,并被移动到Survivor空间上,那么该对象年龄将被设置为1。

对象在Survivor区中每熬过一次YGC/Minor GC,年龄就加一,当他的年龄增加到一定程度,就会被移动到老年代(年龄值默认为15)。

对象晋升老年代的阈值可以通过-XX:MaxTenuringThreshold设置。

3、动态年龄判断并进入老年代(伴随YGC产生的)

为了更好的适应不同程序的内存状况,虚拟机并不是永远要求对象的年龄必须达到MaxTenuringThreshold才会晋升到老年代。

如果在Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需达到MaxTensuringThreshold的要求年龄。

(相同age对象大小之和>1/2存活区(即s0或者s1)则所有>=age的对象就会进入老年代)

举个栗子:

比如:MaxTenuringThreshold 为15,Survivor内存大小为100M。age 为1的,所有对象大小之和为10M。age 为5的,所有对象大小之和为51M。age为6的,所有对象大小之和为5M.

因为age 为5的对象所占内存之和已经超过了Survivor空间的一半,所以age为5,和age大于5的对象,都要移到老年代(没有age达到15的限制)

4、一次Young GC时数据放到存活区,但是存活区满了导致放不下去此时直接进入老年代

尽可能避免这种情况,如果对象直接从Eden区到老年代,那么存活区就没有什么存在的意义了,之所以设置存活区,就是为了将没有引用的对象更早的回收掉,将内存腾出来。

Full GC

当老年代满了之后,触发Full GC。

Full GC 范围:

整个堆内存(年轻代+老年代)+园数据区

对堆的回收:

标记--清扫

对堆标记,对象是否被引,被引用的为存活对象。

对园数据回收:

标记--清扫

标记类,哪些类失效了。

回收,将失效的类卸载掉。

FGC时长,大小跟内存大小有关系,内存大,则FGC时间长。

时长不太好控制,但是我们可以控制FGC频次。

当老年代和年轻代,被存活的对象占满时(GC也不能将这些存活的对象清理掉),在Eden就不能再创建新的对象,导致OOM。

http://www.itcdns.cn/skill/detail/1586233667857

一、OOM含义:

OOM,全称“Out Of Memory”,意思是“内存用完了”。 它来源于java.lang.OutOfMemoryError。

官方介绍为当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出 java.lang.OutOfMemoryError :···

(注意:这是个很严重的问题,因为这个问题已经严重到不足以被应用处理)。

gc的触发条件

触发条件:

YGC:

有且只有这一种情况,eden满了,触发gc

FGC:

1、老年代满了

2、园区某些类已经失效了,在加载的找不到这个类,也会触发FGC,去卸载这个类,释放这个类。

3、空间担保原则(主要触发fgc的方式)

4、代码里面显示调用

5、jmap dump

内存担保机制

现代虚拟机把新生代分为三个区域,一个Eden区域,两个Survivor区域,Eden区域与Survivor区域的比例大小是8:1,虚拟机在YGC/Minor GC时在新生代采用复制算法,将存活对象复制到一个Survivor上面,如果Survivor空间不够用时,就需要老年代进行分配担保。

在发生Minor GC之前虚拟机会先检查老年代最大可用的连续空间是否大于新生代对象的总空间。如果这个条件成立,那么Minor GC可以确保是安全的。如果不成立,虚拟机会查看HandlePromotionFailure设置值是否允许担保失败。如果允许,虚拟机会继续检查老年代最大可用的连续空间是否大于历次晋升到老年代的平均年龄(因为事先不知道存活对象的内存空间,所以取了平均值)。若果大于,虚拟机会尝试进行一次Minor GC,但是这次Minor GC存在风险。如果小于,或者HandlePromotionFailure不允许担保,那这次也要改为Full GC

空间担保原则:

每次ygc的时候,都会往老年代里放对象。

根据历史每次往老年代放的对象大小,根据一个算法,估算这一次要放对象大小。估算的数值,小于老年代剩余内存,就执行ygc。

如果大于老年代剩余空间,放弃本次ygc,直接fgc。

代码里面显示调用

代码里写了system.gc或者get run time .gc

fgc特别消耗cpu,尽可能把FGC频次减少,最起码要一小时以上

java进程之间以及跟JVM是什么关系

1.程序的运行是以进程在内存中的运行形式体现的。当你启动一个程序时,系统会调用其对应进程进入内存运行,图中进程的pid即为进程的唯一标识符。然后进程之间是并发执行的。准确的说,你启动的是java程序,但系统运行的是进程,因为程序是静态的,进程才是动态的,也就是程序并不会进入内存运行,而是其对应进程进入内存运行。

2.是公用一个JVM的,这个就类似你电脑自己的操作系统,打开两个程序肯定是在同一个系统内存中运行的,原因就是我问题一中说的进程是并发执行的。

命令行启动的java程序是共用一个jvm的,启动一个程序就是在jvm中开启一个进程,每个进程至少有一个线程,当然可以有多个线程,

线程之间通信比较简单,就像java书上讲的一样,但进程间的通信复杂点,如管道、内存映射、内存共享、消息队列、socket等,你可以简单理解为两个进程间没关系

2个进程肯定是2个jvm实例

二、监控GC命令

1、jstat监控Java进程的GC情况

登陆服务器

ssh root@47.95.122.13

查看java进程

ps -ef|grep java

监控fgc次数和时间

jstat -gcutil 22893 2000

jstat  -gcutil  [Java的pid] 2000 20 (间隔2s,总共打印20次)

jstat -gcutil 22278 2000

查看gc的情况(内存使用百分比及gc的总时间,gc次数)

总结

到此这篇关于JVM的基本介绍以及垃圾回收的文章就介绍到这了,更多相关JVM垃圾回收内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JAVA JVM运行时数据区详解

    目录 一.前言 二.运行时数据区整体概架构 三.程序计数器 四.虚拟机栈 1.栈的特点 2.栈帧的内部结构 3.局部变量表 4.操作数栈 5.动态链接 6.方法返回地址 五.本地方法栈 六.堆 1.设置堆大小的参数 2.对象分配过程 3.堆中的GC 4.内存分配策略 5.什么是TLAB 6.堆是分配对象存储的唯一选择吗? 七.方法区 1.方法区概述 2.设置方法区内存大小 3.如何解决OOM问题? 4.方法区存储什么 5.方法区的演进细节 6.方法区的GC 总结 一.前言 这是JVM系列文章的第

  • 浅谈JVM 底层解析 i++和 ++i 区别

    目录 一.前言 二.代码实现 三.字节码指令 四.字节码解析 1. 第一类问题 2. 第二类问题 3. 第三类问题 4. 第四类问题 一.前言 如果只用普通的知识解释i++和++i的话 i++ 先将i赋值再++ ++i 先++再赋值 但是这简单的回答并不能入吸引面试官的眼球,如果用java字节码指令分析则效果完全不同 二.代码实现 public class OperandStackTest { /** 程序员面试过程中, 常见的i++和++i 的区别 */ public static void

  • Java JVM编译策略案例详解

    解释器 当虚拟机启动时,解释器可以首先发挥作用,而不必等待编译器全部编译完成再执行,这样可以省去许多不必要的编译时间.并且随着程序运行时间的推移,编译器逐渐发挥作用,根据热点探测功能,,将有价值的字节码编译为本地机器指令,以换取更高的程序执行效率. hotspot中内嵌有2个JIT编译器,分别为Client Compiler,Server Compiler,但大多数情况下我们称之为C1编译器和C2编译器. C1编译器 client compiler,又称C1编译器,较为轻量,只做少量性能开销比较

  • JAVA jvm系列--java内存区域

    目录 一.JVM的组成 二.JVM运行流程 三.java内存区域详解(运行时数据区域) (一)程序计数器 (二)java虚拟机栈 (三)本地方法栈 (四)java堆 (五)方法区 运行时常量池 (六)直接内存 总结 JVM: Java Virtual Machine,Java虚拟机,包括处理器.堆栈 .寄存器等,是用来执行java字节码(二进制的形式)的虚拟计算机. 一.JVM的组成 JVM由以下四部分组成(两个子系统和两个组件): 类加载器(ClassLoader) 执行引擎(Executio

  • java虚拟机JVM类加载机制原理(面试必问)

    目录 1.类加载的过程. 1)加载 2)验证 3)准备 4)解析 5)初始化 2.Java 虚拟机中有哪些类加载器? 1)启动类加载器(Bootstrap ClassLoader): 2)扩展类加载器(Extension ClassLoader): 3)应用程序类加载器(Application ClassLoader): 3.什么是双亲委派模型? 4.为什么使用双亲委派模式? 5.有哪些场景破坏了双亲委派模型? 1)线程上下文类加载器 2)Tomcat 的多 Web 应用程序 3)OSGI 实现

  • JVM的基本介绍以及垃圾回收

    目录 JVM java虚拟机 JVM jvm主要组成部分及其作用 JVM Stack: jvm栈 堆: Jvm heap内存空间划分 Full GC 一.OOM含义: 二.监控GC命令 总结 JVM java虚拟机 JVM java虚拟机是一个可执行java字节码的虚拟机进程.Java虚拟机本质上就是一个程序,java源文件被编译成能被java虚拟机执行的字节码文件,当它在命令行上启动的时候,就开始执行保存在某字节码文件中的指令.Java语言的可移植性正是建立在Java虚拟机的基础上.任何平台只

  • 简单介绍Java垃圾回收机制

    Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Java深受大家欢迎的众多特性之一,能够帮助程序员更好地编写Java程序. 这篇教程是系列第一部分.首先会解释基本的术语,比如JDK.JVM.JRE和HotSpotVM.接着会介绍JVM结构和Java堆内存结构.理解这些基础对于理解后面的垃圾回收知识很重要. Java关键术语 JavaAPI:一系列帮助开发者创建Java应用程序的封装好的库. Java开发工具包(JDK):一

  • Java垃圾回收机制简述

    说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM来处理. 顾名思义,垃圾回收就是释放垃圾占用的空间,那么在Java中,什么样的对象会被认定为"垃圾"?那么当一些对象被确定为垃圾之后,采用什么样的策略来进行回收(释放空间)?在目前的商业虚拟机中,有哪些典型的垃圾收集器?下面我们就来逐一探讨这些问题.以下是本文的目录大纲: 如何确定某个对象是"

  • 浅谈Java垃圾回收的实现过程

    本教程是为了理解基本的Java垃圾回收以及它是如何工作的.这是垃圾回收教程系列的第二部分.希望你已经读过了第一部分:<简单介绍Java垃圾回收机制>. Java垃圾回收是一项自动化的过程,用来管理程序所使用的运行时内存.通过这一自动化过程,JVM解除了程序员在程序中分配和释放内存资源的开销. 启动Java垃圾回收 作为一个自动的过程,程序员不需要在代码中显示地启动垃圾回收过程.System.gc()和Runtime.gc()用来请求JVM启动垃圾回收. 虽然这个请求机制提供给程序员一个启动GC

  • 老生常谈Java虚拟机垃圾回收机制(必看篇)

    在Java虚拟机中,对象和数组的内存都是在堆中分配的,垃圾收集器主要回收的内存就是再堆内存中.如果在Java程序运行过程中,动态创建的对象或者数组没有及时得到回收,持续积累,最终堆内存就会被占满,导致OOM. JVM提供了一种垃圾回收机制,简称GC机制.通过GC机制,能够在运行过程中将堆中的垃圾对象不断回收,从而保证程序的正常运行. 垃圾对象的判定 我们都知道,所谓"垃圾"对象,就是指我们在程序的运行过程中不再有用的对象,即不再存活的对象.那么怎么来判断堆中的对象是"垃圾&q

  • JavaScript中的垃圾回收与内存泄漏示例详解

    前言 程序的运行需要内存.只要程序提出要求,操作系统或者运行时就必须供给内存.所谓的内存泄漏简单来说是不再用到的内存,没有及时释放.为了更好避免内存泄漏,我们先介绍Javascript垃圾回收机制. 在C与C++等语言中,开发人员可以直接控制内存的申请和回收.但是在Java.C#.JavaScript语言中,变量的内存空间的申请和释放都由程序自己处理,开发人员不需要关心.也就是说Javascript具有自动垃圾回收机制(Garbage Collecation). 一.垃圾回收的必要性 下面这段话

  • .NET垃圾回收GC诊断工具dotnet-gcmon使用

    今天介绍一个新的诊断工具 dotnet-gcmon, 也是全局 .NET CLI 工具, 它可以监控到 .NET 程序的 GC, 能获取到的信息也很详细, 另外 maoni 大佬也是其中的开发者之一. 安装 gcmon 和其他的 dotnet 诊断工具一样, 你可以使用以下命令,进行全局安装 dotnet tool install -g dotnet-gcmon 参数介绍 参数 描述 n 进程名, dotnet 应用的进程名 p 进程ID, dotnet 应用的 Process ID m 最小

  • 快速理解Java垃圾回收和jvm中的stw

    Java中Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外).Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互:这些现象多半是由于gc引起. GC时的Stop the World(STW)是大家最大的敌人.但可能很多人还不清楚,除了GC,JVM下还会发生停顿现象. JVM里有一条特殊的线程--VM Threads,专门用来执行一些特殊的VM Operation

  • JVM的垃圾回收机制详解和调优

    文章来源:matrix.org.cn 作者:ginger547 1.JVM的gc概述 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都使用类似的算法管理内存和执行收集操作. 在充分理解了垃圾收集算法和执行过程后,才能有效的优化它的性能.有些垃圾收集专用于特殊的应用程序.比如,实时应用程序主要是为了避免垃圾收集中断,而大多数OLTP应用程序则注重整体效率.理解了应用程序的工作负荷

  • 浅谈jvm中的垃圾回收策略

    java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已经介绍了CLR中GC的对象回收方式,是基于代的内存回收策略,其实在java中,JVM的对象回收策略也是基于分代的思想.这样做的目的就是为了提高垃圾 回收的性能,避免对堆中的所有对象进行检查时所带来的程序的响应的延迟,因为jvm执行GC时,会stop the word,即终止其它线程的运行,等回收完毕,才恢复其它线程的操作.基于分代的思想是:jvm在每一次执行垃圾收集器时,只是对一小部分内存 对象引用进行检查,这一小部分对象的生命周

随机推荐