欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Java内存结构和Java内存泄漏,

来源: javaer 分享于  点击 38251 次 点评:131

Java内存结构和Java内存泄漏,


Java内存结构

方法区:存放要加载的类的信息(名称,修饰符等)、类中的静态变量、类中final类型的常量、类中Field和Method信息。通过Class对象的方法访问的信息来源于方法区。方法区是全局共享的。JVM会回收(GC)方法区中的内存。
堆(Heap):存储对象实例和数组。
本地方法栈: native方法调用的信息。
PC寄存器
JVM方法栈(Stack): 存储基本数据类型 byte short int long float double char boolean;方法的形式参数,方法调用完后从栈空间回收;引用对象的地址,引用完后,栈空间地址立即被回收,堆空间等待GC。

public class Employee {//运行时 jvm把 类信息放入方法区  
    private int employeeId; //放入栈
    private String name; //name引用放入栈 , name对象放入堆  
    private Date onboardDate;
    private String title;
    public Employee(int employeeId, String name) {
        this.employeeId = employeeId;
        this.name = name;
    }
    public int getEmployeeId() {
        return employeeId;
    }
    public String getName() { // 方法本身放入方法区 
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getOnboardDate() {
        return onboardDate;
    }
    public void setOnboardDate(Date onboardDate) {
        this.onboardDate = onboardDate;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj) return true;
        if(!(obj instanceof Employee)) return false;
        Employee employee = (Employee)obj;
        return this.employeeId == employee.employeeId && 
                (this.name == employee.name || 
                   (this.name != null && this.name.equals(employee.name))
                );
    }
    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + employeeId;
        result = 31 * result + name.hashCode();
        return result;
    }       
    public static void main(String[] args) {
        Employee employee = new Employee(1, "Tom");//employee引用 放入栈中 Employee对象放入堆中  
        String name  = employee.getName();
    }
}

Java内存泄漏
如果没有强引用指向堆中的对象,JVM可能GC这个对象,释放堆空间。
下面的情况,因为强引用存在,对象不能被回收,可能造成内存泄漏,出现OutOfMemery错误。

示例 1:

Employee employee = new Employee(1, "Tom");
GregorianCalendar calendar = new GregorianCalendar(2017, 5, 1);
Date date = calendar.getTime();
employee.setOnboardDate(date);
date = null; //Date对象不能被GC,因为employee对象中持有Date对象的强引用
employee = null; //Date对象可以被GC

示例 2:散列集合中的对象的状态被改变,从而改变了hash code, 不能用remove方法删除对象。

Employee employee = new Employee(1, "Tom");
Set<Employee> set = new HashSet<>();
set.add(employee);
employee.setName("Jerry");//the hash code of the object is changed
employee = null; //Employee object can not be GC
set.remove(employee); //cannot remove the object due to hash code changed; 
//Employee object can not be GC
set = null;//Employee object can be GC now

示例 3:内部类对象持有个对外围类对象的引用。
假设Employee类中定义了一个成员类InnerClass,和一个返回InnerClass对象的方法getInnerClass()。

Employee employee = new Employee(1, "Tom");
Employee.InnerClass inner = employee.getInnerClass();
employee = null;//Employee object can not be GC
inner = null;//Employee object can be GC now

SoftReference
WeakReference
PhantomReference

相关文章

    暂无相关文章
相关栏目:

用户点评