JAVA垃圾回收简介.docx
文本预览下载声明
JAVA垃圾回收简介
java中的内存java虚拟机自己往治理的,java的内存分配分为两个部分,一个是数据堆,一个是栈。
堆是给开发代码使用的,是在JVM启动时创建,程序在运行的时候一般分配数据堆,把局部的临时的变量都放进往,生命周期和进程有关系,在堆中分配的内存由java虚拟机的自动垃圾回收器来治理,堆内存用来存放由new创建的对象和数组。
栈是留给JVM自己用的,用来存放类的信息的,它和堆不同,运行期内GC不会开释空间,当超过变量的作用域后,java会自动开释掉为该变量所分配的内存空间:
假如程序声明了static的变量,就直接在栈中运行的,进程销毁了,不一定会销毁static变量。
在函数中定义的基本类型变量和对象的引用变量都在函数的栈内存中分配
java中有垃圾回收机制:System。gc()即垃圾收集机制是指jvm用于开释那些不再使用的对象所占用的内存。java语言并不要求jvm有gc,也没有规定gc如何工作。垃圾收集的目的在于清除不再使用的对象。gc通过确定对象是否被活动对象引用来确定是否收集该对象。
假如你向系统申请分配内存进行使用(new),可是使用完了以后却不回还(delete),结果你申请到的那块内存你自己也不能再访问,该块已分配出来的内存也无法再使用,随着服务器内存的不断消耗,而无法使用的内存越来越多,系统也不能再次将它分配给需要的程序,产生泄露。一直下往,程序也逐渐无内存使用,就会溢出。
堆的上风是可以动态分配内存大小,生存期也不必事先告诉编译器,由于它是在运行时动态分配内存的。缺点就是要在运行时动态分配内存,存取速度较慢。
栈的上风是存取速度比堆要快,缺点是存在栈中的数据大小与生存期必须是确定的,无灵活性。
JAVA垃圾回收原理
在Java虚拟机规范中,提及了如下几种类型的内存空间:
栈内存(Stack):每个线程私有的。
堆内存(Heap):所有线程公用的。
方法区(Method Area):有点像以前常说的“进程代码段”,这里面存放了每个加载类的反射信息、类函数的代码、编译时常量等信息。
原生方法栈(Native Method Stack):主要用于JNI中的原生代码,平时很少涉及。
而Java的使用的是堆内存,java堆是一个运行时数据区,类的实例(对象)从中分配空间。Java虚拟机(JVM)的堆中储存着正在运行的应用程序所建立的所有对象,“垃圾回收”也是主要是和堆内存(Heap)有关。
垃圾回收的概念就是JAVA虚拟机(JVM)回收那些不再被引用的对象内存的过程。一般我们以为正在被引用的对象状态为“alive”,而没有被应用或者取不到引用属性的对象状态为“dead”。垃圾回收是一个开释处于”dead”状态的对象的内存的过程。而垃圾回收的规则和算法被动态的作用于应用运行当中,自动回收。
JVM的垃圾回收器采用的是一种分代(generational )回收策略,共分为三个代:
Young(年轻代)
年轻代分三个区。一个Eden区,两个Survivor区。大部分对象在Eden区中产生。当Eden区满时,还存活的对象将被复制到Survivor区 (两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor往也满了的时候,从第一 个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要留意,Survivor的两个区是对称的,没先后关 系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor往过来的对象。而且,Survivor区总有一个是空的。
Tenured(年老代)
年老代存放从年轻代存活的对象。一般来说年老代存放的都是生命期较长的对象。
Perm(持久代)
用于存放静态文件,如Java类、方法等。持久代对垃圾回收没有明显影响,但是有些应用可能动态产生或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=进行设置。
虚拟内存初始化的时候会把所有对象都分配到 Eden space,并且大部分对象也会在该区域被开释。 当进行?minor GC的时候,VM会把剩下的没有开释的对象从Eden space移动到其中一个survivor spaces当中。此外,VM也会把那些长期存活在survivor spaces 里的对象移动到年老代的“tenured” space中。当 tenured generation 被填满后,就会产生Full GC,Full GC会相对比较慢由于回收的内容包括了所有的 live状
显示全部