Java内存结构和Java内存泄漏
2017-05-16 09:28
162 查看
Java内存结构
方法区:存放要加载的类的信息(名称,修饰符等)、类中的静态变量、类中final类型的常量、类中Field和Method信息。通过Class对象的方法访问的信息来源于方法区。方法区是全局共享的。JVM会回收(GC)方法区中的内存。
堆(Heap):存储对象实例和数组。
本地方法栈: native方法调用的信息。
PC寄存器
JVM方法栈(Stack): 存储基本数据类型 byte short int long float double char boolean;方法的形式参数,方法调用完后从栈空间回收;引用对象的地址,引用完后,栈空间地址立即被回收,堆空间等待GC。
Java内存泄漏
如果没有强引用指向堆中的对象,JVM可能GC这个对象,释放堆空间。
下面的情况,因为强引用存在,对象不能被回收,可能造成内存泄漏,出现OutOfMemery错误。
示例 1:
示例 2:散列集合中的对象的状态被改变,从而改变了hash code, 不能用remove方法删除对象。
示例 3:内部类对象持有个对外围类对象的引用。
假设Employee类中定义了一个成员类InnerClass,和一个返回InnerClass对象的方法getInnerClass()。
SoftReference
WeakReference
PhantomReference
方法区:存放要加载的类的信息(名称,修饰符等)、类中的静态变量、类中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
相关文章推荐
- JVM内存结构及java相关基础知识
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
- 黑马程序员-java的内存结构
- 【转】Java中的OutOfMemoryError和JVM内存结构
- Java之JVM垃圾回收 内存结构以及垃圾回收算法
- Java内存结构
- 内存监控方法之——Jmap结合Memory Analyzer,分析java程序是否存在内存泄漏
- JAVA程序内存结构
- 深入理解java虚拟机(一):java内存区域(内存结构划分)
- 深入理解java虚拟机(一):java内存区域(内存结构划分)
- Java 内存结构
- JAVA内存结构详解
- Java内存结构和Java垃圾回收机制
- JVM之---Java内存结构(第二篇)
- Java对象内存结构
- 关于Java中多维数组的内存结构分析
- Java基础 数组_排序,查找,进制转换,内存结构
- Java对象内存结构
- java中HashMap结构以及内存相关
- java中的进程与线程及java对象的内存结构【转】