【问题标题】:What is the memory overhead of a Java method?Java 方法的内存开销是多少?
【发布时间】:2009-04-08 14:35:24
【问题描述】:

类中函数的内存开销是多少?

例如,

Class A
{
 int a
}

Class B
{
 int a
 int foo(int);
}

所以 100 个 A 类实例应该是 80 个字节。 100 个 B 类实例呢?

【问题讨论】:

  • 不叫函数。它被称为方法。
  • 大声笑,是的,它被称为方法,你最好做一个测试。
  • 它是不可测试的,除非通过查看 VM 源代码,除非您执行其他人正在执行的操作并假设序列化形式与内存中的形式相同。
  • 假设序列化形式与内存中的表示有任何关系是无稽之谈。我猜他们做了太多的 C 编程,这样的滥用很猖獗。
  • 好吧,你也可以看看虚拟机内存。 “创建A的100个对象,看内存”对B来说也是如此。我会为你做一个适当的测试。

标签: java memory


【解决方案1】:

开销是……没有。

方法定义和代码地址存储在 Class 对象中,该对象具有唯一的实例,您的对象的每个实例都指向该实例。 既然是这样,无论您是否添加了该方法,每个单独对象的开销都不算什么。

【讨论】:

  • 我不明白反对票,因为答案是准确的。
  • 不是我,但这个答案并不完全正确。方法定义的维护存在开销,即使开销是固定的并且不依赖于实例的数量。我们能有一百万种方法吗?如果否,则存在开销。
【解决方案2】:

80 字节,因为对象中不包含方法。除非你也在谈论“vtable”类型的东西,在这种情况下可能是 160 个字节。

关于 160 字节的说明。如果每个对象都分配了自己的 vtable(这是一种可能的实现),则 160 将是。或者(正如在 cmets 中指出的那样)更好的方法是每个类一个 vtable,这意味着 80 + 指向 vtable 的指针的大小(可能是 4 或 8 个字节,具体取决于 VM)。所以 84 或 88 字节。

这整个事情完全取决于 VM 分配内存和处理非最终方法的方式。在不知道特定 VM 是如何实现的情况下,这两个问题都无法正确回答。

【讨论】:

  • 两个类都有某种对其类的引用(相当于 C++ vtbl 指针)。并不是每个对象都会在任何类型的合理 VM 上携带大量的类信息。
  • 这是一个特定于 VM 的实现,因为它是一个 C++ 编译器特定的实现。
  • Tom,当您评论我的回答时,您似乎过于以 Sun 实施为中心。如果您不能考虑还有其他可能的 VM 实现,那么我不知道该说什么。
【解决方案3】:

正如其他一些人至少说过的那样,方法没有存储在序列化中。

您可以使用以下代码轻松地在此示例中进行测试。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;


public class SerializationTest {

    public static void main(String[] args) {
        serialize(true);
        serialize(false);
    }

    public static void serialize(boolean aOrB) {
        FileOutputStream fos = null;
        ObjectOutputStream out = null;
        try {
            fos = new FileOutputStream("output.txt");
            out = new ObjectOutputStream(fos);
            out.writeObject(aOrB ? new A() : new B());
            out.close();
            fos.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        File file = new File("output.txt");
        System.out.println(file.length());
    }

    public static class A implements Serializable {
        int a = 0;
    }

    public static class B implements Serializable {
        int a = 0;

        public int foo(int a) {
            return a;
        }
    }
}

对我来说这是打印出来的

48
48

【讨论】:

  • 然而,序列化不一定反映数据在正在运行的虚拟机中的分配方式。
【解决方案4】:

对于 32/64 位 JVM,这两个类的对象将使用大约 20-24 字节。

【讨论】:

    【解决方案5】:

    该方法未以序列化形式存储。就这么简单。

    编辑:对于VM中的对象在执行过程中,无论对象的类有多少方法,大小都应该是恒定的。

    【讨论】:

      【解决方案6】:

      等于,80! (总之)

      【讨论】:

        【解决方案7】:

        v-table 指针的大小可能四舍五入到 16 的倍数。

        【讨论】:

        • 两个对象的类都会对它们的类​​有某种引用。
        猜你喜欢
        • 2017-02-20
        • 2010-10-18
        • 2013-05-20
        • 1970-01-01
        • 1970-01-01
        • 2014-02-14
        • 1970-01-01
        • 2010-09-30
        • 2011-02-12
        相关资源
        最近更新 更多