Java 引用的种类

原创 2015年11月20日 16:31:52
    我们在写程序的时候通过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。

相关文章推荐

Java的内存回收——Java引用的种类

1、Java引用的种类        Java是面向对象的编程语言,一个Java程序往往需要创建大量的Java类,然后对各Java类创建大量的Java对象,再调用这些Java对象的属性和方法来操作它们...

Java内存回收机制--Java引用的种类(强引用、弱引用、软引用、虚引用)

写在前面:对Java有一定认识的人都知道,Java有垃圾回收机制,尽管如此,Java同样也会出现内存泄露,本篇系列主要介绍Java的内存回收机制,以及介绍开发过程中内存管理的小技巧。本文参考《疯狂Ja...

Java面试题整理二(各种类的区别对比)

面试官:你这项目很丰富啊!来给我讲讲  xxxxxxxx类和yyyyyyy类的区别。 小白:NIMA我又不是Java的设计者,而且项目中又没有用过,我怎么可能知道它们的区别。(精神崩溃后的回答) 面试...

java线程池的种类和应用

Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 new...
  • paul342
  • paul342
  • 2016年09月05日 19:36
  • 1903

Java 中import的用法,以及类的种类

问: 已经定义了一个包Human;包里定义一个类Human  1):  我在这个包外重新写个程序,import整个Human包,但是Human 不是公共的,为什么啊,不是引用了整个包后就...

Java菜鸟面试突破系列之事物方方面面(事物种类特性及隔离级别、悲观锁和乐观锁等)

数据库事物的方方面面(包含特性及隔离级别、悲观锁和乐观锁等)纲要:本篇文章主要汇总网络上关于这方面的总结以应对校招,哈哈哈,介绍数据库事物相关的方方面面,从事物谈起,提及事物的特性、隔离级别、以及数据...

Java中异常种类处理总结

---------------------- http://edu.csdn.net/heima" target="blank">android培训、http://edu.csdn.net/heima...

Java中Exception的种类

通常来讲,Java中的异常会被分为三种: Error: 这种异常被设计成不被捕获,因为这种异常产生于JVM自身。 Runtime Exception: 运行时异常往往与环境有关,编译时无法检查,并...

Java 内部类种类及使用解析

Java 内部类种类及使用解析
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java 引用的种类
举报原因:
原因补充:

(最多只允许输入30个字)