Java 引用的种类

    我们在写程序的时候通过New 创建Java 对象,可以认为是Java对象申请内存空间。JVM中会在堆内存中为每个对象分配空间,当一个Java对象失去引用时,JVM垃圾机制会自动清楚它们并且清除他们所占的内存空间。
    Java 内存管理管理包括穿件Java对象申请空间和回收Java对象内存回收,这两个工作都是JVM自动完成。对于垃圾回收机制来说,判断一个对象是否有可回收的标准就是在于对象是不是被引用。为了更好的管理对象的引用。JDK1.2开始Java在java.lang.ref 包下提供了三个类:SoftRefenrence、PhantomReference、WeakerReference、他们分别代表了系统对象的三种引用方式:软引用,虚引用、弱引用。归纳起来Java公用四中引用状态:

- 强引用
- 软引用
- 弱引用
- 虚引用

强引用

Java程序中最常见的引用,程序创建一个对象并把这个对像赋给一个引用变量,这个引用变量就是强引用。强引用是Java程序中使用最广泛的应用类型,被强引用所引用对象不会被JVM回收。即使系统内存非常紧张;即使有些Java对象以后永远不会被用到,JVM也不会强制回收引用对象,内存不够就会造成Java内存泄露。
下面的例子
package refer;

class Person{
    String name;
    int age;
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return "this person name is :"+ this.name+" age is :"+this.age;
    }
}
public class StrongReferenceTest {
    public static void main(String[] args) {
        Person [] persons = new Person[100000];
        for ( int i=0;i<persons.length;i++){
            persons[i] = new Person("name"+i, i);
        }
        System.out.println(persons[2].toString());
        System.gc();
        System.runFinalization();
        System.out.println(persons[5].toString());
    }
}

然后右击修改运行参数 Run Configurations
这里写图片描述
这里写图片描述
出现
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.lang.AbstractStringBuilder.<init>(AbstractStringBuilder.java:45)
at java.lang.StringBuilder.<init>(StringBuilder.java:92)
at refer.StrongReferenceTest.main(StrongReferenceTest.java:18)

软引用

软引用需用通过SoftReference类来实现,当一个对象只有具有软引用的时候,他有可能被垃圾回收机制回收。对于软引用的对象而言,当内存足够的时候,他可能不会被系统回收,程序可以继续使用该对象;当内存不够的时候系统就会回收它。软引用通常用于对内存敏感的程序中。当系统内存不足的时候JVM就回收它,避免系统内存不足的异常。
package refer;

import java.lang.ref.SoftReference;

class Person{
    String name;
    int age;
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return "this person name is :"+ this.name+" age is :"+this.age;
    }
}
public class SoftReferenceTest {
    public static void main(String[] args) {
        SoftReference<Person>[] persons = new SoftReference[100000];
        for ( int i=0;i<persons.length;i++){
            persons[i] = new SoftReference<Person>(new Person("name"+i,i));
        }
        System.out.println(persons[2].get());
        System.gc();
        System.runFinalization();
        System.out.println(persons[5].get());
    }
}

然后右击修改运行参数 Run Configurations
这里写图片描述
这里写图片描述
出现

null
null

JVM自动回收

弱引用

弱引用和软引用有点类似,但是弱引用的所引起的生命周期更短。弱引用通过WeakReference类实现,弱引用和软引用很像。到弱引用的引用级别更低。对于只有弱引用的对象而言,当运用垃圾回收机制时候,不管系统内存是否够用,总会回收系统所占的内存。
    弱引用有很大的不确定性,因为每次垃圾回收垃圾机制执行都会回收所引用的对象,而且垃圾回收机制的运行不受程序员的控制,因此在使用弱引用的时候可能出现空指针异常的问题。
package refer;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

class Person{
    String name;
    int age;
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return "this person name is :"+ this.name+" age is :"+this.age;
    }
}
public class WeakReferenceTest {
    public static void main(String[] args) {
        WeakReference<Person>[] persons = new WeakReference[10];
        for ( int i=0;i<persons.length;i++){
            persons[i] = new WeakReference<Person>(new Person("name"+i,i));
        }
        System.out.println(persons[2].get());
        System.gc();
        System.runFinalization();
        System.out.println(persons[2].get());
    }
}

运行结果如下:

this person name is :name2 age is :2
null

虚引用

软引用和虚引用可以单独使用,单虚引用不能单独使用,单独使用虚引用没有太大的意义。虚引用主要就是跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用队列事都包含了虚引用,从而了解虚引用对象是否检查对象回收。
引用队列是有java.lang.ref.ReferenceQueue 类表示,它用于保存被回收对象的引用。当把软引用、弱引用和引用队列联合使用系统回收被引用的对象之后,将会把被回收对象引用添加到关联的引用添加队列中。与软引用和弱引用不同的是,虚引用在对象被解释之前,将把它对应的虚拟引用添加到它的关联引用队列中,这使得可以对象在被回收之前采取行动。
package refer;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

class Person{
    String name;
    int age;
    public Person(String name,int age){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        return "this person name is :"+ this.name+" age is :"+this.age;
    }
}
public class PhantomReferenceTest {
    public static void main(String[] args) {
        Person person = new Person("nameTest", 5);
        ReferenceQueue<Person> rfq = new ReferenceQueue<Person>();
        PhantomReference<Person> pph = new PhantomReference<Person>(person, rfq);
        System.out.println(pph.get());
        System.gc();
        System.runFinalization();
        System.out.println(rfq.poll()==pph);
    }
}

打印的结果

null
false
因为系统无法通过虚引用来获得被引用的对象,所以执行第一个结果是Null,当执行垃圾回收之后,虚引用的对象被垃圾回收,对应的引用将被添加到关联的引用队列中,因此第二个看到输出的是true。

猜你喜欢

转载自blog.csdn.net/u011462448/article/details/49945337