JAVA中的垃圾回收与内存分配-2

详解内存分配

通过上一篇文章,我们大题了解了变量和对象都是如何在栈内存和堆内存中分配的,那么我们继续了解。
还是老套路先上个图:

栈,就如同它的名字一样,JVM中的栈内存也是一个后进先出LIFO的数据结构,JVM的垃圾回收器对于并非用new开辟的内存区域,就显得无能为力(来自《JAVA编程思想》第四版中文版P87)。垃圾回收器只知道释放那些由new分配的内存。所以为了应对这种情况,便有了finalize()方法。(详细内容,查资料)
要注意一点的是finalize()并不等同于C++中的析构函数。而Java中的垃圾回收符合下面的条件:

  1. 对象可能不被垃圾回收
  2. 垃圾回收并不等于“析构”

    栈内存与栈操作

    如上面的图中所示,运行时数据区中有两个栈空间:JVM栈和本地方法栈。
    栈,常常与线程“联系”在一起,这是因为每当启动一个新线程时,Java虚拟机都会为它分配一个Java栈。
    Java栈以帧为单位保存线程的运行状态。虚拟机只会直接对Java栈执行两种操作:以帧为单位的压栈和出栈。
  • JVM栈
    JVM栈也就是虚拟机栈,它是线程私有的,也就是说是线程隔离的,即每个线程都有自己独立的虚拟机栈。它的生命周期与线程相同。
    JVM栈描述的是java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
    每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
  • 本地方法栈
    本地方法栈的功能和特点类似于虚拟机栈,均具有线程隔离的特点以及都能抛出StackOverflowError和OutOfMemoryError异常。
    不同的是,本地方法栈服务的对象是JVM执行的native方法,而虚拟机栈服务的是JVM执行的java方法。详细内容后续更新……

JVM栈之栈上内存分配

在JVM中,堆是线程共享的,因此堆上的对象对于各个线程都是共享和可见的,只要持有对象的引用,就可以访问堆中存储的对象数据。虚拟机的垃圾收集系统可以回收堆中不再使用的对象,但对于垃圾收集器来说,无论筛选可回收对象,还是回收和整理内存都需要耗费时间。
如果确定一个对象的作用域不会逃逸出方法之外,那可以将这个对象分配在栈上,这样,对象所占用的内存空间就可以随栈帧出栈而销毁。在一般应用中,不会逃逸的局部对象所占的比例很大,如果能使用栈上分配,那大量的对象就会随着方法的结束而自动销毁了,无须通过垃圾收集器回收,可以减小垃圾收集器的负载。JVM允许将线程私有的对象打散分配在栈上,而不是分配在堆上。分配在栈上的好处是可以在函数调用结束后自行销毁,而不需要垃圾回收器的介入,从而提高系统性能。
heaptoStack

Java堆内存

堆内存

Donate comment here