代码之家  ›  专栏  ›  技术社区  ›  adrian.tarau

Applet与独立Java进程之间的XMX差异

  •  0
  • adrian.tarau  · 技术社区  · 17 年前

    我有一个小程序,它需要多少内存取决于客户端有多少数据。

    我们通常建议使用Java 1.6最新版本,但是实际上我们支持Java 1.5 +,所以我们在applet中有一个保护,它显示了一个对话框,上面有一个关于“内存不足”的警告,以及指示去哪里增加内存。

    然而,我很惊讶地发现-xmx在小程序和独立进程中的工作方式不同,我无法确定小程序是否有足够的内存。

    这是如何做到的:

    • 小程序接收以下参数:
      • PARAM名称=“JavaAdTalk”值=“-XMX153M”(当然,它在Java 1.6更新10中工作,否则它将在Java 1.5和Java 1.6之前更新10中获得64米)。
      • param name=“required.memory”value=“153”参数
    • 在运行时,我们比较 要求内存 具有 runtime.getruntime().maxmemory()。
    • 小程序中的限制为153m时,我们得到143589376,但在独立应用程序中,我们得到155516928
    • 153*1000*1000=153000000(我不是用1024换1K,以防万一),绝对超过143589376。

    如果我使用0.9的系数来避免JVM中的任何近似值,那么看起来效果很好,但是这是正确的值-0.9吗?他们如何计算这个限制,为什么在独立的应用程序和小程序中它是不同的?

    2 回复  |  直到 17 年前
        1
  •  2
  •   Kevin Montrose    17 年前

    在Java内存上的尖峰时间。

    首先,在Java中内存不足 OutOfMemoryError )受正在运行的GC的特性影响。

    与名称的含义相反,您可以在不实际耗尽内存的情况下得到一个OutofMemoryError;当运行时决定花费大量的时间gc'ing时,也会抛出它。( source 埋在那里)。

    此外,您可以通过耗尽特定的 种类 记忆。请记住,Java GC是一个代际收集器,如果你恰巧耗尽了几代人(我想说的是“终身”),但我可能错了,你也会失去记忆。这意味着可以从OS视图中留出堆空间,但是无法在Java堆上分配任何东西。

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


    在您的案例中,更可能发生的是以下方面的一些变化:您的代码在独立和小程序上下文中运行,每个上下文都有不同的安全管理器和不同的启动行为;这意味着涉及到一组不同的类(这些类会进入永久代),具有不同的DEP持久性。我想小程序的“堆栈”会更厚,因为它们的行为受到了更强烈的约束,这可能解释了maxmemory()中的大部分差异。

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

        2
  •  0
  •   adrian.tarau    17 年前

    Kevin,的确,与桌面应用程序相比,小程序运行方式的差异是有意义的,但令我吃惊的是,小程序和桌面应用程序之间的最大(我认为更大)内存差异很大,大约为8%。如果你说的“小程序”堆栈越厚,越强烈的冲突对他们行为的限制“我希望小程序能获得更大的最大内存,而不是独立版本。

    我在applet和应用程序之间进行了一些测量。两个都接收到相同的参数(-xmx128m),都使用相同的jvm运行- Java热点(TM)64位服务器VM版本113-B02(第一次我认为Applet与客户端JVM一起运行,桌面用服务器JVM运行,但似乎都是服务器JVM)

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

    • applet:-d_uujvm_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
    • 独立:-xrunjdwp:transport=dt_socket,address=127.0.0.1:54876,suspend=y,server=n-xmx128m-dfile.encoding=utf-8

    小程序:最大内存=119.314K

      • PS伊甸园空间:14592K
      • PS幸存者空间:14.528K
      • PS老一代:87.424K
        • 总计:116.544K
    • 非堆
      • 内存池代码缓存:49.152K
      • Mem Pool PS Perm发电机:86.016K
        • 总计:135.168K

    桌面:最大内存=129.302K

      • PS伊甸园空间:8.704K
      • PS幸存者空间:3.008K
      • PS老一代:116.544K
        • 合计:126.272K
    • 非堆
      • 内存池代码缓存:49.152K
      • 内存池PS Perm Gen:65.536K
        • 总计:135.168K

    这两个合资企业之间的巨大差异

    • ps perm gen,applet得到了一个更大的块-这是有意义的,因为applet可能会加载与独立版本相比的附加类(但即使在这种情况下,“old gen”也要小得多,这很奇怪,因为通常所有这些附加类最终都会进入“old gen”)。
    • 堆内存,eden/survivor/old gen之间的比率完全不同。applet的old gen是standalone的old gen的75%,这是一个很大的区别,我会说,如果希望(olmost)相同的内存模型,我会很好,因为当我作为applet或桌面应用程序运行应用程序时不应该有任何区别。

    现在我更困惑了,不仅是我不知道如何计算最大内存比(实际上0.9在未来的JVM版本中是无效的),而且我的应用程序在作为小程序运行时可能会耗尽内存。为了安全起见,当它作为小程序运行时,我需要增加大约10-15%的最大内存。

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

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