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

  • 拥有5000多个巨大的行类或几个500-1000个行类(如果它们全部都被加载了)会更好吗?
  • 每次实例化对象时,是否都唯一的额外内存使用情况是实例变量引用
  • 对于没有实例变量的5000行类,加载该类时的成本规模是多少。.类文件的大小是近似值吗?
  • jar文件的大小是否表明类将占用的常规或最大内存大小?

  • 在cruftex的答案后编辑:
    这是我对类拆分的理解:
  • 拆分为逻辑块可以很好地改善代码重用性,并且
    减少行数
  • 它还使您更容易理解和
    维护代码

  • 这是我现在对类加载的理解:
  • 第一次使用时,将类加载到内存中(使用的内存大约是类文件的大小)
  • 如果使用JIT,则JIT编译器会创建一些其他机器友好的二进制版本,该版本会使用更多的内存
  • 如果使用Hotspot,则仅使用机器友好版本对某些常用类进行优化(以平衡内存和速度)
  • 加载类后,创建其他实例的开销可以忽略不计(大约50-100字节?)(假设没有实例变量)
  • 一旦加载了一个类,该类本身就不会被垃圾回收

  • 这大概是如何工作的吗?

    最佳答案



    通常没关系。一般而言,各种形式的代码仅占总内存使用的一小部分(例如5%)。因此,即使您确实设法将代码大小减少了一半,总的内存使用量也只会少量减少。

    相反,过长的源文件使代码库难以导航,而较大的作用域则使得更难获得有关类的确切作用以及某些更改是否安全的概述。因此,较长的源文件会使修改代码的成本大大增加并且容易出错。



    正确的。



    热点是准时制,因此您在这里重复一遍。但是,是的,JIT确实增加了代码大小(但是增加了更多的速度)。



    那是特定于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);
        }
    }
    



    尽管Java语言规范没有对此进行强制性规定,但我曾经使用的每个JVM在其ClassLoader变得不可访问时都会释放一个类(当然,引导类加载器将始终保持可访问性,但是自定义ClassLoader可能会变得不可访问)。

    10-01 02:29