我想知道当Java编写的程序运行时,它的类将全部加载到主内存中?

我想知道当Java编写的程序运行时,它的类将全部加载到主内存中?,java,eclipse,Java,Eclipse,当一个用Java编写的程序运行时,它的所有类是否都会加载到主内存中?如果是这样,这不是浪费RAM吗?不,这很好,因为有虚拟地址空间和虚拟内存。请阅读以下内容: 虚拟内存意味着您可以将大量内容加载到内存中,未使用的部分保存到光盘中,并从物理RAM中移出 虚拟地址空间意味着每个进程(一个进程的一个示例是Java程序)都有自己的地址空间,因此它不会从其他进程“窃取”地址。只加载在特定执行过程中引用的类。大多数大型Java程序经常会运行许多未加载的类,因为这些类服务于该特定进程未执行的各种场景 标准

当一个用Java编写的程序运行时,它的所有类是否都会加载到主内存中?如果是这样,这不是浪费RAM吗?

不,这很好,因为有虚拟地址空间和虚拟内存。请阅读以下内容:

虚拟内存意味着您可以将大量内容加载到内存中,未使用的部分保存到光盘中,并从物理RAM中移出


虚拟地址空间意味着每个进程(一个进程的一个示例是Java程序)都有自己的地址空间,因此它不会从其他进程“窃取”地址。

只加载在特定执行过程中引用的类。大多数大型Java程序经常会运行许多未加载的类,因为这些类服务于该特定进程未执行的各种场景

标准库中的类与应用程序类的处理方式相同。例如,如果应用程序不引用AWT,则不会加载AWT包中的任何类

Java语言规范包含明确排除类初始化的措辞

:

将创建一个类或接口类型T 在紧接 第一次出现任何一种 以下:

  • T是一个类,T的一个实例是 创造
  • T是一个类和一个静态变量 调用由T声明的方法
  • A 由T声明的静态字段是 分配的
  • 由T声明的静态字段 已使用,并且该字段不是 恒定变量(§4.12.4)
  • T是一个 顶级类和断言 词汇嵌套语句(§14.10)
注意我使用的术语“初始化”。在解析定义类的二进制数据时,类被初始化为构造类对象的一部分

没有任何东西可以阻止特定的类加载器实现将它看到的所有类的二进制文件加载到内存中,但是它不能完全加载这些类,除非它们被请求而不违反JLS


对于常见的类加载器实现,请参阅URLClassLoader。

这是一个公平的问题。它不在内存中,而是在VM的内存中,除非需要,否则不会浪费RAM。类不是在启动时全部加载,而是按需加载。@aetheria请记住,类加载的确切时间不由规范定义。无法保证按需加载。精确的语义只存在于类初始化中。这取决于加载的确切含义。。。当然,在ClassLoader.loadClass(名称)定义的加载意义上,并没有急切的加载。这将找到类,解析其二进制文件并对其进行初始化。事实上,无法保证JVM将加载和不加载哪些类。当执行引用类X的代码路径时,可以保证JVM将加载和初始化类X。在相反的情况下,可以保证JVM不会初始化类X,除非执行引用它的代码路径。在这种情况下,无法保证是否会加载该类,但实际上,JVM实现不会浪费加载不必要的类的资源。首先,标准库的很大一部分将在启动时加载。另外,只要从JAR访问一个类,一个实现就可以优化速度,一次加载整个JAR。@Marko,我在回答您的评论时添加了更多信息。希望这有助于澄清。是的,类初始化具有严格的计时语义。这一点很重要,因为其中涉及Java代码,而它运行的确切时间对于程序的正确性很重要。就内存而言,这只会影响静态变量和分配给它们的对象所占用的内存。类代码本身已经加载到永久生成中,在大多数情况下,它的内存占用占主导地位。