Java 堆、非堆和堆栈..垃圾收集的复杂性

Java 堆、非堆和堆栈..垃圾收集的复杂性,java,performance,garbage-collection,jvm-hotspot,Java,Performance,Garbage Collection,Jvm Hotspot,我一直在经历java中的垃圾收集(jdk 6 hot spot JVM),我有几个问题希望社区能帮助我解决 我的理解是: 1) 堆分为 a)Code Cache b)Perm generation. a) 年轻一代-伊甸园和幸存者:新的物体和阵列正在诞生 创建到年轻一代。小的垃圾收集将 在年轻一代中运作。仍处于活动状态的对象将 从伊甸园空间移动到幸存者空间 b) 老一代/终身一代:主要收藏将仍然活着的对象从年轻一代移动到老一代 2) 非堆分为 a)Code Cache

我一直在经历java中的垃圾收集(jdk 6 hot spot JVM),我有几个问题希望社区能帮助我解决

我的理解是:

1) 堆分为

    a)Code Cache
    b)Perm generation.
a) 年轻一代-伊甸园和幸存者:新的物体和阵列正在诞生 创建到年轻一代。小的垃圾收集将 在年轻一代中运作。仍处于活动状态的对象将 从伊甸园空间移动到幸存者空间

b) 老一代/终身一代:主要收藏将仍然活着的对象从年轻一代移动到老一代

2) 非堆分为

    a)Code Cache
    b)Perm generation.
我想知道的:

1)what if survivor gets full..how will minor garbage collection work.

2)When and how is the perm generation garbage collected.
3)Also what happens to the stack..where is it stored or residing?How is its size controlled?
  • 当幸存者空间已满时,对象将移动到旧代。虽然从技术上讲,大多数情况下,当一个对象从幸存者空间移动到老一代时,这并不是因为幸存者空间已满,而是因为该对象已经历了一定数量的小收集,通常为10-15次
  • 很少。它主要是Java类的二进制代码,因此只有从内存中卸载一组类时才能释放空间。大多数程序在整个程序生命周期中使用相同的类集,因此收集永久生成通常是浪费时间。基本上,Java只会在内存即将耗尽时在这里进行收集
  • 堆栈是堆之外的东西,它的大小是由这样一个事实控制的,即只有在保证对象的生命周期有限的情况下,对象才会存储在堆栈上。这些都是局部变量。假设您有一个本地
    StringBuilder
    变量,用于构建方法的返回值。您从不将其传递到自己的方法之外,而是调用
    stringBuilder().toString()
    在方法末尾创建一个新对象。由于Java可以判断
    StringBuilder
    对象在方法运行期间不会过期,因此它可以将其放在堆栈上,并在方法返回时立即取消分配,而不是将其传递给垃圾收集器

  • 堆栈大小通过在创建时固定来控制。如果试图使用比堆栈上可用空间更多的空间,则会出现“堆栈溢出”异常。

    堆栈是内存的一部分。本地自动变量在此堆栈上创建,并传递方法参数。当一个进程启动时,它会得到一个默认的堆栈大小,该大小对于每个进程都是固定的。在今天的操作系统中,通常默认堆栈大小为1MB,这对于大多数进程来说已经足够了。在异常情况下,堆栈限制超过。这称为堆栈溢出。

    如果幸存者已满,则对象将移动到旧一代。您有多个问题。感谢您的回答。。。对于pt 2,只有在应用程序未部署的情况下才会发生类的卸载?我说的对吗?我正在检查我的一个应用程序,其中jconsole捕获的perm Generation图形是锯齿形的图形…您如何解释…这可能是因为同样驻留在perm中的字符串实习生吗gen@Rips对取消部署应用程序后,可以在永久生成中释放空间,但详细信息在很大程度上取决于旧一代使用的垃圾收集器。如果我们谈论热点JVM,就不可能在堆栈上分配StringBuilder对象。JVM可以内联所有StringBuilder方法,并将其字段转换为方法范围内的局部变量。这样,StringBuilder对象就不会在堆中分配。不过,用于组成字符串的临时字符[]将以任何方式分配到堆上。