【问题标题】:Java's varying available heap sizeJava 不同的可用堆大小
【发布时间】:2019-05-03 18:12:54
【问题描述】:

我刚刚发现有一些库可以计算 java 对象的浅层大小,所以我想我也可以用一种非常简单的方式来编写它。这是我尝试过的。

  1. 用一些Xmx 启动程序说A
  2. 创建您想要计算其大小的类型的对象(比如T)并将它们存储在一个列表中,这样 GC 就不会清理它们。
  3. 当我们遇到 OOM 时,让代码处理它并清空列表。
  4. 现在检查我们分配的T 类型对象的数量。让它成为n
  5. 进行二分搜索找出增量,以便成功分配n+1 对象。

这是代码,我试过了

import java.util.ArrayList;
public class test {
    public static void main(String[] a) {
        ArrayList<Integer> l = new ArrayList<>();
        int i=0;
        try {
            while(true) {
                l.add(new Integer(1));
                i++;
            }
        } catch(Throwable e) {
        } finally {
            l.clear();
            System.out.println(i + "");
        }
    }
}

但我注意到,在每次运行中为相同的 Xmx 分配的对象数量是不同的。为什么是这样? JVM里面有什么随机的吗?

【问题讨论】:

  • 分配对象的数量不是也非常依赖于其他变量的聚合,因为它们都存储在堆中吗?你有一个数组列表和 int 也占用空间。 (只是一个奇怪的想法)。此外,按照我的理解,JVM 使用操作系统分发的可用资源。如果是这种情况,则可能会有一个不断变化的堆。
  • @JoshThrasher 每次运行不应该是一个常数吗?
  • 确实如此。我想知道如果你会得到明显更小的结果,你是否在后台运行了一堆东西。如果是这样,那将支持 JVM 仅分配可用资源的想法。
  • 没有,我的笔记本电脑一直都有足够的可用内存 (~50%)

标签: java heap-memory


【解决方案1】:

JVM 中的某些事件是不确定的,这会影响垃圾收集器的行为。

但可能有一些因素会导致在填满堆之前创建可变数量的(您的)对象。其中包括:

  • 并非堆中的所有对象都是您明确创建的ArrayListInteger 对象。当您调整 ArrayList 的大小时,将创建 Object[] 对象、由您的 println 调用生成的各种对象......以及其他在后台发生的事情。

  • 堆大小调整行为。堆的大小不会立即调整为 -Xmx 大小。 JVM 通常从较小的堆大小开始,并根据需要对其进行扩展。当您获得 OOME 时,JVM 很可能已将堆扩展到允许的最大值,但扩展顺序可能对...各种因素很敏感,包括一些可能不确定的因素。

  • 堆代。典型的 Java GC 使用旧空间和新空间。旧空间包含长寿命的物体。新对象被分配到新空间......除非它们非常大。对象的实际分布会影响 GC 何时运行,以及 JVM 何时决定堆满。

  • JIT 编译。在应用程序执行的某些时刻,JVM 将(通常)决定 JIT 编译您的代码。发生这种情况时,会分配额外的对象。


简而言之:我不希望您的基准测试能够为可以创建的对象数量提供一致的结果。

【讨论】:

    猜你喜欢
    • 2017-04-27
    • 1970-01-01
    • 2021-01-20
    • 2011-11-24
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    相关资源
    最近更新 更多