堆内存:用于存储使用new关键字所创建的对象;
栈:用于存储所有局部变量。
调用方法时,栈中分配该方法的栈针,栈针中包括参数和局部变量
方法执行结束,栈针被清除,局部变量清除。
方法区:1:存储类的信息{.class及方法}
2:方法只有一份,通过this区分对象。
JVM内存分为“堆”、“栈”和“方法区”三个区域,分别用于存储不同的数据。
堆内存用于存储使用new关键字所创建的对象;
栈内存用于存储程序运行时在方法中声明的所有的局部变量;
方法区用于存放类的信息,Java程序运行时,首先会通过类装载器载入类文件的字节码信息,经过解析后将其装入方法区。类的各种信息(包括方法)都在方法区存储。
引用变量也是存放在栈中
- Foo foo = new Foo();
- foo.f();
以上代码的内存实现原理为:
1.Foo类首先被装载到JVM的方法区,其中包括类的信息,包括方法和构造等。
2.在栈内存中分配引用变量foo。
3.在堆内存中按照Foo类型信息分配实例变量内存空间;然后,将栈中引用foo指向foo对象堆内存的首地址。
4.使用引用foo调用方法,根据foo引用的类型Foo调用f方法。
JVM垃圾回收机制
垃圾回收机制是Java提供的自动释放内存空间的机制。
垃圾回收器(Garbage Collection,GC)是JVM自带的一个线程,用于回收没有被引用的对象。
Java程序会出现内存泄露
一般来说内存泄漏有两种情况。一是在堆中分配的内存,在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉;另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它的访问方式(引用)。第一种情况,在Java中已经由于垃圾回收机制的引入,得到了很好的解决。所以,Java中的内存泄漏,主要指的是第二种情况。
下面给出了一个简单的内存泄露的例子。在这个例子中,我们循环申请Object对象,并将所申请的对象放入一个List中,如果我们仅仅释放引用本身,那么List仍然引用该对象,所以这个对象对GC来说是不可回收的。代码如下所示:
- List list=new ArrayList(10);
- for (int i=1;i<100; i++)
- {
- Object o=new Object();
- list.add(o);
- o=null;
- }