Java:为什么它使用固定数量的内存?或者它是如何管理内存的?

Java:为什么它使用固定数量的内存?或者它是如何管理内存的?,java,memory,memory-management,jvm,Java,Memory,Memory Management,Jvm,JVM似乎使用了一些固定数量的内存。至少我经常看到参数-Xmx(用于最大大小)和-Xms(用于初始大小)表明 我觉得Java应用程序不能很好地处理内存。我注意到一些事情: 即使是一些非常小的示例演示应用程序也会加载大量内存。这可能是因为加载了Java库。但是为什么需要为每个Java实例加载库呢?(看起来是这样的,因为多个小应用程序线性占用更多内存。有关我在哪里描述此问题的详细信息,请参阅。)或者为什么这样做 像Eclipse这样的大型Java应用程序经常会因一些OutOfMemory异常而崩溃

JVM似乎使用了一些固定数量的内存。至少我经常看到参数
-Xmx
(用于最大大小)和
-Xms
(用于初始大小)表明

我觉得Java应用程序不能很好地处理内存。我注意到一些事情:

  • 即使是一些非常小的示例演示应用程序也会加载大量内存。这可能是因为加载了Java库。但是为什么需要为每个Java实例加载库呢?(看起来是这样的,因为多个小应用程序线性占用更多内存。有关我在哪里描述此问题的详细信息,请参阅。)或者为什么这样做

  • 像Eclipse这样的大型Java应用程序经常会因一些OutOfMemory异常而崩溃。这总是很奇怪,因为我的系统上仍然有大量可用内存。通常,它们在运行时消耗越来越多的内存。我不确定他们是否有一些内存泄漏,或者这是由于内存池中的碎片造成的——我感觉后者就是这样

  • Java库似乎比类似的强大库(例如Qt)需要更多的内存。为什么会这样?(要进行比较,请启动一些Qt应用程序,查看它们的内存使用情况,并启动一些Java应用程序。)

为什么它不使用底层系统技术,比如
malloc
free
?或者,如果他们不喜欢libc实现,他们可以使用(比如在FreeBSD和中),这看起来相当不错。我非常确信,这将比JVM内存池性能更好。而且不仅性能更好,还需要更少的内存,特别是对于小型应用程序


另外:有人已经试过了吗?我对基于LLVM的Java JIT编译器非常感兴趣,它只使用
malloc
/
free
进行内存处理

或者,这也可能因JVM实现而异?我主要使用了Sun JVM


(还要注意:这里我不是直接谈论GC。GC只负责计算可以删除哪些对象并初始化内存释放,但实际释放是另一个子系统。好吧,这是一些自己的内存池实现,而不仅仅是调用
free



编辑:一个非常相关的问题:或者换一种说法:为什么JVM处理内存分配的方式不同于本机应用程序?

Java确实使用了
malloc
free
,或者至少JVM的实现可能是这样的。但是,由于Java跟踪分配和垃圾收集无法访问的对象,它们显然是不够的

至于你课文的其余部分,我不确定是否有问题

即使是一些非常小的示例演示应用程序也会加载大量内存。这可能是因为加载了Java库。但是为什么需要为每个Java实例加载库呢?(看起来是这样的,因为多个小应用程序线性占用更多内存。请参阅此处了解我在哪里描述此问题的一些详细信息。)或者为什么这样做

这可能是由于启动和运行JVM的开销造成的

像Eclipse这样的大型Java应用程序经常会因一些OutOfMemory异常而崩溃。这总是很奇怪,因为我的系统上仍然有大量可用内存。通常,它们在运行时消耗越来越多的内存。我不确定他们是否有一些内存泄漏,或者这是由于内存池中的碎片造成的——我感觉后者就是这样

我不完全确定你所说的“经常撞车”是什么意思,因为我认为这已经很久没有发生在我身上了。如果是,可能是因为您前面提到的“最大大小”设置


你问Java为什么不使用
malloc
free
的主要问题归结为目标市场的问题。Java的设计目的是消除开发人员对内存管理的头痛。java的垃圾回收器在释放内存时,可以很好地释放内存,但是java并不是在内存限制的情况下与C++竞争。Java很好地完成了它想要做的事情(消除了开发人员级内存管理),JVM也很好地承担了这一责任,这对于大多数应用程序来说已经足够好了

Java在启动时分配一个“堆”内存,或一个固定大小的块(Xms参数)。它实际上并没有立即使用所有这些内存,但它告诉操作系统“我需要这么多内存”。然后,当您在Java环境中创建对象和工作时,它会将创建的对象放入预先分配的内存堆中。如果该内存块已满,那么它将从操作系统请求多一点内存,直到达到“最大堆大小”(max heap size)(-Xmx参数)

一旦达到最大大小,Java将不再从操作系统请求更多的RAM,即使有很多空闲内存。如果您尝试创建更多的对象,那么就没有堆空间了,您将得到OutOfMemory异常。 现在,如果您正在查看Windows任务管理器或类似的东西,您将看到使用X兆内存的“java.exe”。这种类型对应于它为堆请求的内存量,而不是堆内使用的内存量

换句话说,我可以编写应用程序:

class myfirstjavaprog
{  
    public static void main(String args[])
    {
       System.out.println("Hello World!");
    }
}
基本上只需要很少的内存。但如果我用cmd行运行它:

java.exe myfirstjavaprog -Xms 1024M
然后,在启动时,java会立即向操作系统请求1024MB的ram,这将在Windows任务管理器中显示。实际上,这个ram并没有被使用,但java保留了它供以后使用

相反,如果我有一个尝试创建10000字节大数组的应用程序:

class myfirstjavaprog
{  
    public static void main(String args[])
    {
       byte[] myArray = new byte[10000];
    }
}
但是用命令行运行它:

java.exe myfirstjavaprog -Xms 100 -Xmx 100
那么Java只能支持