-letmlet与独立Java进程之间的差异

时间:2009-07-14 13:48:19

标签: java memory settings

我有一个小程序需要更多或更少的内存,具体取决于客户端有多少数据。

我们通常建议使用Java 1.6最新版本,但我们实际上支持Java 1.5+,因此我们在applet中有一个保护,它显示一个对话框,其中包含“内存不足”的警告以及说明如何增加存储器中。

但是,我很惊讶地发现-Xmx在applet和独立进程中的工作方式不同,我实际上无法确定applet是否有足够的内存。

以下是如何完成的:

  • applet收到以下参数:
    • param name =“java_arguments”value =“ - Xmx153m”(当然这适用于Java 1.6 update 10,否则它将在Java 1.5和Java 1.6之前的更新10中获得64M)
    • param name =“required.memory”value =“153”
  • 在运行时,我们将 required.memory Runtime.getRuntime()进行比较.maxMemory()
  • 在applet中限制为153M我们得到143589376但在独立应用程序中我们得到155516928
  • 153 * 1000 * 1000 = 153000000(我不会使用1024 for 1K,以防万一),绝对超过143589376.

如果我使用因子0.9来避免JVM中的任何近似似乎运行良好,但这是正确的值 - 0.9?他们如何计算此限制以及为什么它在独立应用程序和applet中有所不同?

2 个答案:

答案 0 :(得分:2)

Java内存的时间。

首先,Java中的内存不足(即实际获得OutOfMemoryError)受到正在运行的GC的特性的影响。

与名称所暗示的相反,您可以获得OutOfMemoryError而不会实际耗尽内存;它也会在运行时决定花费大量时间GC(source,它埋在那里)时抛出。

此外,您可以通过耗尽特定的内存来获取OutOfMemoryError。请记住,Java GC是一代分类收集器,如果你碰巧耗尽了其中一代(我想说“终身”一代,但我可能错了)你也有效地失去记忆。这意味着您可以从操作系统视图中留下堆空间,但无法在Java堆上分配任何内容。

最后,有一些与GC相关的实际开销可能占用了一些堆空间。


在您的情况下更有可能发生的事情是以下的一些变体:您的代码在独立和applet上下文中运行,每个上下文都有不同的安全管理器和不同的启动行为;这意味着涉及一组不同的类(它们被敲入永久代),具有不同的依赖性。我认为applet“stack”更厚,因为它们的行为受到更严格的限制,这可能是maxMemory()中差异的主要原因。

简而言之,可用内存的差异可能是由于Java运行时为其自己的操作保留的内存的一些变化。这可能与GC相关,与安全策略相关,或者只是为Applet环境加载的不同类与独立类加载。在确定返回什么时,Runtime.maxMemory()也可以考虑上述任何“内存不足”条件。因此,0.9值可能是实施副作用,可能在将来发生变化。

答案 1 :(得分:0)

凯文,确实在applet的运行方式与桌面应用程序之间的区别是有意义的,但让我印象深刻的是,applet和a之间的最大内存(我认为更大)存在很大差异桌面应用程序,大约是8%。如果你说“applet”堆栈“由于对行为的更严格限制而更厚”我期待applet将获得更大的最大内存而不是独立版本

我在applet和应用程序之间进行了一些测量。两者都接收相同的参数(-Xmx128M),两者都使用相同的JVM运行 - Java HotSpot(TM)64位服务器VM版本11.3-b02(我第一次认为applet运行时客户端JVM和桌面运行时服务器JVM,但它似乎都与服务器JVM一起运行)

当然,JVM实际上收到了不同的参数,但没有什么重要的(我认为):

  • applet:-D__jvm_launched = 426431678538 -Xbootclasspath / a:/usr/jvm/64/jdk1.6.0_13/jre/lib/deploy.jar:/usr/jvm/64/jdk1.6.0_13/jre/lib/ javaws.jar:/usr/jvm/64/jdk1.6.0_13/jre/lib/plugin.jar -Xmx128m
  • standalone:-Xrunjdwp:transport = dt_socket,address = 127.0.0.1:54876,suspend = y,server = n -Xmx128M -Dfile.encoding = UTF-8

小程序:最大记忆= 119.314K

    • PS伊甸园空间:14,592K
    • PS幸存者空间:14.528K
    • PS Old Gen:87.424K
      • 总计:116.544K
  • 非堆
    • 内存池代码缓存:49.152K
    • Mem Pool PS Perm Gen:86.016K
      • 总计:135.168K

桌面:最多记忆= 129.302K

    • PS Eden Space:8.704K
    • PS幸存者空间:3.008K
    • PS Old Gen:116.544K
      • 总计:126.272K
  • 非堆
    • 内存池代码缓存:49.152K
    • Mem Pool PS Perm Gen:65.536K
      • 总计:135.168K

这两个JVM之间的巨大差异

  • PS Perm Gen,applet得到了更大的一块 - 这是有道理的,因为与独立版本相比,applet可能会加载额外的类(但即使在这种情况下,“Old Gen”也要小得多,这很奇怪,因为通常所有那些额外的课程最终将进入“老一代”)
  • 堆积记忆,Eden / Survivor / Old Gen.App Gen的老一代的比例完全不同,是独立的Old Gen的75%,这是一个很大的不同我会说,如果期待(最近)相同的记忆模型,我很善良因为当我将应用程序作为applet或桌面应用程序运行时应该没有任何区别。

现在我更加困惑,不仅仅是我不知道如何计算max.memory比率(事实上0.9对未来的JVM版本无效)但是我的应用程序在运行时可能会内存不足小程序。

,当它作为小程序运行时,我需要增加大约10-15%的最大内存。

我仍然不相信为什么这样一个不同的堆比率(在同一台机器上)和一个较小的堆(特别是考虑到applet需要额外的类)。

有什么原因吗?我现在好奇,这超出了我需要检查applet是否具有我认为应该的最大内存量。