【问题标题】:Java JVM Keep Memory Allocation Against Operating SystemJava JVM 保持针对操作系统的内存分配
【发布时间】:2011-10-02 08:26:44
【问题描述】:

我在 windows 7 64bit 上运行 1.6.0_25 64bit。

我试图让 JVM 以最大内存运行,因为我的应用程序非常占用内存......但遗憾的是......内存分配没有建立,并且有很多来自 Windows 的页面错误不断带来下一组虚拟内存。

我正在运行 java -Xms2G -Xmx3G 测试

以下代码是我尝试将整个文件带入...这样我就不会遇到页面错误以进行读取。

File f = new File("veryLARGEfile.txt");
FileInputStream in = new FileInputStream(f);
int i = (int) f.length();
System.out.println("Bytes in file: " + i);

byte[] file = new byte[i];
i = in.read(file);
System.out.println("Bytes read: " + i);

执行此方法我可以看到,在 Windows 任务管理器中,系统在读取文件时达到了 2G 的内存...但是一旦完成读取...内存又回落了!!!!

这是一个主要问题...我需要将整个字节数组留在活动内存中。

谢谢你, 哎


我已修改代码以使用基本数组类型 int[][] 和 float[][] 来保存我的数据,而不是保留包含 int 和 float 的对象的 ArrayList。

这样做,我发现我的 java 内存没有被交换(所以,我猜堆内存的处理方式与这里的堆栈有点不同)[哦,我确实将所有代码也更改为静态类型 - 我知道,非常糟糕的编程风格]

我现在遇到的问题是如何处理我的 HashMap...我尝试构建查找表的所有尝试都以 O(n^2) 运行时间来构建失败!!!

【问题讨论】:

  • 所以如果我做对了,你是在故意制造内存泄漏吗?或者您需要文件始终存在于内存中?我有兴趣了解您的用例..
  • 您在加载文件后是否保留对byte[] file 的引用?你的系统有多少内存?您的其余代码如何处理此文件?
  • 实际上...我最初是使用 BufferReader 读取一个 1GB 的文件并将输入和输出处理到 BufferedWriter... 该系统应该创建近 5GB 的处理数据。可悲的是,观察内存使用情况,它在 6 小时内从 30K 增加到 .5G 非常缓慢,并且每增加几个 k 字节,就会完成另外一到两次 IO 读取......
  • 这听起来像是一个用例,人们会非常尝试避免将整个文件保存在内存中(特别是因为通过 IO 流 API 很容易做到这一点)。
  • 继续...所以我重新编写了代码以快速加载数据。所以,好消息,确实如此,它会在 2 分钟内加载......但是一旦加载完成并且我准备好使用数据,内存就会恢复,然后我开始看到非常严重的页面错误。跨度>

标签: java jvm memory-management page-fault


【解决方案1】:

决定将进程内存的哪些部分保留在 RAM 中以及换出哪些部分是由操作系统决定的,而不是由 JVM 决定的。通常,操作系统会将频繁访问的内存保留在 RAM 中 - 如果不是,您为什么需要它?

可能有一些操作系统 API 允许您在 RAM 中“固定”某块内存,但 Java 并未公开此功能。

但是根据您的要求,您应该考虑拥有文件memory-mapped 而不是显式读取它。它可能会快得多。

【讨论】:

  • 好的...那么,我如何处理我正在读取的数据以预先设定的起始大小出现在 ArrayLists 和 HashMaps 中的事实,这是被分页的部分。 .而且我正在实现的算法非常占用内存...建议我转移到 Linux...这里的问题...它的行为会有所不同并允许我将 ArrayLists 保留在活动内存中吗?
  • @Enas:由于分页是操作系统的事情,不同的操作系统可能会有不同的行为。 Windows 的消费者版本往往针对最终用户应用程序而不是数据处理进行优化。迁移到 Windows Server 操作系统也可能导致不同的分页行为。虽然我会说,一旦你的算法对所有数据进行了密集工作,它就应该在任何健全的操作系统上被分页。
  • 谢谢,这很有意义。我正在考虑安装基于系统的 Linux,看看是否能解决它……你会推荐 Ubuntu 还是有更好的“服务器”行为 Linux 发行版。谢谢。
【解决方案2】:

Java 相当努力地将其所有应用程序保留在内存中,或者换一种说法,它作为最后的手段进行交换,因为如果它的任何内存被交换到磁盘,它的性能就会非常糟糕。

如果您的 Java 应用程序正在交换到磁盘,那是因为您的应用程序为您拥有的系统使用了过多的内存。如果您的应用程序是内存密集型的,并且您必须使用这么多内存,我建议确保您的系统有足够的内存。顺便提一句。您可以花 500 美元购买 8 GB 的服务器,花 1000 美元购买新的 16 GB 工作站。 ;)

【讨论】:

  • 我在一个有 24G 内存和 24G 虚拟内存的系统上运行。我现在正计划消除虚拟内存,从而强制系统使用所有可用的物理内存...
  • 你确定这是导致交换的原因吗?如果你有 24 GB 并且正在使用 ~3 GB,我不明白你为什么要交换到虚拟内存。您的系统上一定有其他原因导致此问题。
猜你喜欢
  • 2016-08-06
  • 1970-01-01
  • 1970-01-01
  • 2017-07-11
  • 2018-08-15
  • 2012-10-29
  • 2021-10-16
  • 1970-01-01
  • 2019-08-20
相关资源
最近更新 更多