java内存管理(垃圾收集器、内存泄漏)

1:java的垃圾收集器的优点:

C语言要求显式地分配内存、释放内存(程序在需要时分配内存,不需要是释放内存)。但常常引起“内存泄漏”,即由于某种原因使得分配的内存没有得到释放。

现比之下,java不需要显式的分配与释放内存,避免很多潜在问题。java在创建对象时自动分配内存,并当该对象引用不存在时释放内存。

Java使用垃圾收集器的技术来监视java程序的运行,当对象不再使用时,就自动释放对象所使用的内存。

Java使用一系列软指针来跟踪对象的各个引用,(之所以称为软指针,是因为他们直接指向对象,而是对象的引用),使用软指针,java垃圾收集器能够以单独的线程在后台运行(并不是独立的平台,有平台依赖),并依次检查各个对象,通过更改对象表项,垃圾收集器可以检查、移除、标记对象等操作。

垃圾收集器是自动运行的,无需显式的请求垃圾收集器。垃圾收集器会检查对象的的各个引用,并回收无引用对象所占用的内存。调用System类中的静态gc()可以运行垃圾收集器,但并不保证立即回收指定对象。(当引用没有被抛弃时,也会有内存耗尽的情况)

垃圾收集机制是为所有的java应用进程服务的,而不是某个特定的进程服务,所以一个进程不能命令垃圾收集器。

默认finalize()(释放资源)方法返回后,对象消失,垃圾收集器开始执行释放内存。

 

如果有一个对象的句柄a,且当a作为构造器的参数,例new constrauctor(a),则即使将a复制为null,a也不符合垃圾收集器的收集标准,直到构造器构造的新对象被赋值空值时,a才可以被垃圾回收器收集。

例如:

Object so= new Object();   

Object so = null;  

Object so= new Object();

 so = new Object();

因为第2行将so赋值为null ,所以第一行的so符合垃圾收集器的收集标准,而第4行相当于将so赋值为null,所以第3行的so也符合垃圾收集器的收集标准。

 

例2:

Object ao= new Object();   

Object bo= new Object();

Object co= new Object();

ao = bo;

ao = co;

co = null;

ao= null;

第4行对象ao的句柄指向bo,所以此行的执行不能使得ao符合垃圾收集器的标准;

第5行同理;

第6行也是没有;

第7行的co符合,因为co指向单一的地址空间;在6行的时候co已经被赋值为null,但是此时co还指向着ao,所以co不符合;而在第7行ao也被赋值成null,此时co指向的地址空间已经被完全赋予了空值;所以此时co符合垃圾收集器的标准。但是ao和bo仍然无法判断。

 

总言之,判断一块内存空间是否符合垃圾收集器的标准:

a.给对象赋予了空值null,以后再也没有调用过。

b.给对象赋予了新值,即重新分配了内存空间。

 

一块内存空间符合垃圾收集器的标准,并不意味着这块空间就一定会被垃圾收集器收集,

 

2:java是如何管理内存的?

Java的内存管理就是内存的分配和释放问题,程序员需要通过关键字new来为每个对象申请内存空间(基本类型除外),所有对象都是在中分配空间。

对象的释放是在GC中完成,(即内存的分配是在程序中完成,内存的释放是在GC中完成),这种方式简化了程序员的工作,但是加重了JVM的工作。也是java程序运行速度较慢的原因之一(因为GC为正确释放对象,必须监控每个对象的运行状态)

GC的工作原理就像是有向图,有向边是从引用者指向被引用对象,每个线程对象可作为图的起点,如果某个对象对根节点不可达,那么认为此对象不再被引用,可以GC回收。

如:

public static void main(){

Object o1=new Object();

Object o1=new Object();

o2=o1;

}

 

 

3:java中的内存泄漏?

内存泄漏就是存在一些被分配的对象,此对象有两种特征

1)对象是可达的,即在有向图中,存在通路可以与其相连

2)对象是无用的,即程序不会再使用这些对象,

这些对象不会被GC回收但是却占用内存

 

C++中,内存泄漏会更大,有些对象被分配内存空间,却不可达,C++中没有GC,所以内存永远不会被回收,

Java中这些不可达的对象都由GC回收,因此java程序员可以不考虑这部分的内存泄漏

 

C++中,程序员需要自己管理边和顶点,对于java来说只需要管理边就好,(不用管理顶点的释放),所以java的效率更高。

 

一个内存泄漏的例子:

Vector v = new Vector(10);

for(int i=0;i<10;i++){

Object o = new Object();

v.add(o);

o=null;

}

此程序所有的Object对象都没有被释放。

对于o,仅仅释放引用本身,那么Vector仍然引用该对象,所以此对象对GC不可回收,因此如果对象加入到Vector后,还必须从Vector中删除,最简单的方法将Vector对象设置为null。

(程序是可以运行,但存在内存泄漏)

 

猜你喜欢

转载自blog.csdn.net/qq_39667655/article/details/81631864
今日推荐