Java应用程序中每个类的成本—更少的大型类或几个较小的类

Java应用程序中每个类的成本—更少的大型类或几个较小的类,java,performance,jakarta-ee,memory,Java,Performance,Jakarta Ee,Memory,对于添加到Java应用程序中的每个新类,内存成本是多少 最好是有5000多行的大类,还是有几个500-1000行的类(如果所有类都已加载) 每次实例化对象时,唯一的额外内存使用是实例变量引用,这是真的吗 对于没有实例变量的5000行类,加载该类时的成本比例是多少。。类文件的大小是粗略的近似值吗 jar文件的大小是否表示类将占用的内存的常规大小或最大大小 根据cruftex的回答进行编辑: 这是我对类拆分的理解: 拆分成逻辑块可以很好地提高代码重用和性能 减少行数 这也使它更容易理解和理解

对于添加到Java应用程序中的每个新类,内存成本是多少

  • 最好是有5000多行的大类,还是有几个500-1000行的类(如果所有类都已加载)
  • 每次实例化对象时,唯一的额外内存使用是实例变量引用,这是真的吗
  • 对于没有实例变量的5000行类,加载该类时的成本比例是多少。。类文件的大小是粗略的近似值吗
  • jar文件的大小是否表示类将占用的内存的常规大小或最大大小
根据cruftex的回答进行编辑: 这是我对类拆分的理解:

  • 拆分成逻辑块可以很好地提高代码重用和性能 减少行数
  • 这也使它更容易理解和理解 维护代码
这是我现在对类加载的理解:

  • 第一次使用时,类被加载到内存中(使用的内存大致等于类文件的大小)
  • 如果使用JIT,JIT编译器将创建一些额外的机器友好型二进制版本,这将使用更多的内存
  • 如果使用Hotspot,则只使用一些常用的类,并使用机器友好的版本进行优化(以平衡内存和速度)
  • 加载类后,创建额外实例的开销可以忽略不计(大约50-100字节?)(假设没有实例变量)
  • 一旦类被加载,类本身就永远不会被垃圾收集

这大概就是它的工作原理吗?

您的问题无法得到具体的回答,所以我尝试用一般的方式来回答。你的问题旨在消耗内存。然而,如果您节省内存,您的性能很可能会因此受到影响,这就是所谓的时空权衡。见:

如果您只关心程序大小,那么保存内存的最简单方法就是完全关闭即时编译器。通过这种方式,您可以为java类的机器代码保存程序存储。顺便说一句:有很多虚拟机选项会影响内存消耗

最好是有5000多行的大类,还是有几个500-1000行的类(如果所有类都已加载)

一般来说,在较小的单元中更可能更好地重用代码。这意味着,当您瞄准较小的尺寸时,可能会节省代码行

如果代码/方法保持不变,而您只是在类之间分配它们,那么会为类增加额外的开销

即使你问了三位专家,让他们看一下代码,他们也会给出不同的答案,因为这在很大程度上取决于你的真实代码、使用模式以及JIT在运行时对它所做的操作

也就是说,即使是一个实验也可能会把你引向错误的方向,因为你需要模拟相同的使用模式

关于这一点的最后一个注意事项是:查看您的VM加载了多少类,并决定是否真的值得保存一个视图

每次实例化对象时,唯一的额外内存使用是实例变量引用,这是真的吗

加上内存管理的恒定开销

对于没有实例变量的5000行类,加载该类时的成本比例是多少。。类文件的大小是粗略的近似值吗

没有JIT:是的

jar文件的大小是否表示类将占用的内存的常规大小或最大大小

不,一点也不,因为类只在需要时加载

一些建议:

如果您担心程序的内存使用,请首先检查堆两次。为此,我推荐jmap和eclipse内存分析器

然后,您可以查看您的类和方法。您可以通过:-XX:-printcomployment调试JIT并查看编译后的方法需要多少空间

对于添加到Java应用程序中的每个新类,内存成本是多少

这通常并不重要。一般来说,只有一小部分(比如说5%)的内存被各种形式的代码占用。因此,即使您成功地将代码大小减少了一半,总体内存使用量也只会略微减少

相比之下,过长的源文件使代码库难以导航,更大的作用域使我们更难了解类的确切功能以及某个更改是否安全。因此,长源文件使得修改代码的成本大大增加,并且容易出错

  • 第一次使用时,类被加载到内存中(使用的内存大致等于类文件的大小)

  • 如果使用JIT,JIT编译器将创建一些额外的机器友好型二进制版本,这将使用更多的内存
  • 如果使用Hotspot,则只使用一些常用的类,并使用机器友好的版本进行优化(以平衡内存和速度)
Hotspot是一个JIT,所以您在这里重复您自己。但是是的,JIT确实增加了代码大小(但速度提高得更多)

加载类后,创建额外实例的开销可以忽略不计(大约50-100字节?)(假设没有实例变量)

这是JVM特有的。在Oracle Hotspot JVM上,每个对象的内存开销约为8字节,如下程序所示:

public class Test {
    public static void main(String[] args) {
        Object[] array = new Object[10_000_000];
        Runtime rt = Runtime.getRuntime();
        long usedBefore = rt.totalMemory() - rt.freeMemory();
        for (int i = 0; i < array.length; i++ ) {
            array[i] = new Object();
        }
        long usedAfter = rt.totalMemory() - rt.freeMemory();
        System.out.println(usedBefore);
        System.out.println(usedAfter);
        System.out.println((double)(usedAfter - usedBefore) / array.length);
    }
}
公共类测试{
公共静态void main(字符串[]args){
Object[]数组=新对象[10_000_000];
Runtime rt=Runtime.getRuntime();
long usedBefore=rt.totalMemory()-rt.freemory();
for(int i=0;i