I have an applet which needs more or less memory depending on how many data the client has.
我有一个applet需要更多或更少的内存,具体取决于客户端有多少数据。
We usually recommend to use Java 1.6 latest version, but we actually support Java 1.5+ so we have a protection in the applet which shows a dialog box with a warning about "not enough memory" and instructions where to go to increase the memory.
我们通常建议使用Java 1.6最新版本,但我们实际上支持Java 1.5+,因此我们在applet中有一个保护,它显示一个对话框,其中包含“内存不足”的警告以及增加内存的说明。
However, I was really surprised to see that -Xmx works differently in applets and standalone processes and I cannot actually determine if the applet has enough memory.
但是,我很惊讶地看到-Xmx在applet和独立进程中的工作方式不同,我实际上无法确定applet是否有足够的内存。
Here is how it is done:
以下是它的完成方式:
- the applet receives the following arguments :
- param name="java_arguments" value="-Xmx153m" (of course this works in Java 1.6 update 10, otherwise it will get 64M in Java 1.5 and Java 1.6 prior update 10)
- param name="required.memory" value="153"
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”
- at runtime, we compare required.memory with Runtime.getRuntime().maxMemory()
- with a limit of 153M in an applet we get 143589376 but in a standalone application we get 155516928
- 153 * 1000 * 1000 = 153000000 (I'm not using 1024 for 1K, just in case ) which is definitely more than 143589376.
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用于1K,以防万一)这绝对超过143589376。
If I'm using a factor of 0.9 to avoid any approximations in JVM seems to work well, but is this the right value - 0.9? How do they calculate this limit and why is it different in standalone applications and applets?
如果我使用因子0.9来避免JVM中的任何近似似乎运行良好,但这是正确的值 - 0.9?他们如何计算此限制以及为什么它在独立应用程序和applet中有所不同?
2 个解决方案
#1
Time for a spiel on Java memory.
Java内存上的时间。
First, running out of memory in Java (ie. actually getting an OutOfMemoryError) is influenced by the peculiarities of the GC that's running.
首先,Java中的内存不足(即实际获得OutOfMemoryError)受到正在运行的GC的特性的影响。
Contrary to what the name implies, you can get an OutOfMemoryError without actually running out of memory; its also thrown when the runtime decides its spending an inordiate amount of time GC'ing (source, its buried in there).
与名称所暗示的相反,您可以获得OutOfMemoryError而不会实际耗尽内存;它也会在运行时决定花费大量时间GC(源,它埋在那里)时抛出。
Additionally, you can get an OutOfMemoryError by running out of specific kinds of memory. Remember that the Java GC is a generational collector, and if you happen to exhaust one of the generations (I want to say the "tenured" one, but I could be wrong) you're also effectively out of memory. This means you can have heap space left from the OS view, but be unable to allocate anything on the Java heap.
此外,您可以通过耗尽特定类型的内存来获取OutOfMemoryError。请记住,Java GC是一代分类收集器,如果你碰巧耗尽了其中一代(我想说“终身”一代,但我可能错了)你也有效地失去记忆。这意味着您可以从OS视图中留下堆空间,但无法在Java堆上分配任何内容。
Finally, there's some actual overhead associated with the GC that could be eating up some heap space.
最后,与GC相关的一些实际开销可能占用了一些堆空间。
What's more likely to be happening in your case, is some variant on the following: your code runs in both a standalone and an applet context, each context has a different security manager and a different startup behavior; this implies that a different set of classes (which get knocked into the permanent generation) are involved, with different dependencies. I'd guess that the applet "stack" is thicker given the more strigent constraints on their behaviors, and that probably accounts for most of the difference in maxMemory().
在您的情况下更有可能发生的是以下变体:您的代码在独立和小程序上下文中运行,每个上下文都有不同的安全管理器和不同的启动行为;这意味着涉及一组不同的类(它们被敲入永久代),具有不同的依赖性。我认为applet“stack”更厚,因为它们的行为受到更严格的限制,这可能是maxMemory()中差异的主要原因。
In short, the difference in available memory is probably due to some change in memory reserved by the Java runtime for its own operation. This could be GC related, security policy related, or just the different classes loaded for the Applet environment vs. the standalone one. Runtime.maxMemory() may also take any of the above "out of memory" conditions into account when determining what to return. Accordingly the 0.9 value is probably an implementation side-effect, one which may change in the future.
简而言之,可用内存的差异可能是由于Java运行时为其自身操作保留的内存的一些变化。这可能与GC相关,与安全策略相关,或者只是为Applet环境加载的不同类与独立类加载。在确定返回什么时,Runtime.maxMemory()也可以考虑上述任何“内存不足”条件。因此,0.9值可能是实施副作用,可能在将来发生变化。
#2
Kevin, indeed it makes sense to be a difference between how an applet runs compared with a desktop application, but what struck me is that there is a big difference in maximum(bigger that I thought) memory available between an applet and a desktop application, which is ~8%.If it is as you said "applet "stack" is thicker given the more strigent constraints on their behaviors" I was expecting that the applet will get a bigger maximum memory and not the stand-alone version.
凯文,确实让applet与桌面应用程序的运行方式有所区别是有意义的,但让我印象深刻的是applet和桌面应用程序之间的最大内存(我认为更大)内存存在很大差异,这是〜8%。如果你说“applet”堆栈“由于对其行为的更严格限制而更厚”我期待applet将获得更大的最大内存而不是独立版本。
I took some measurements between the applet and the application. Both received the same parameters(-Xmx128M), both are running with the same JVM - Java HotSpot(TM) 64-Bit Server VM version 11.3-b02(first time I thought the applet was running with client JVM and desktop was running with server JVM, but it seems both are with server JVM)
我在applet和应用程序之间进行了一些测量。两者都接收到相同的参数(-Xmx128M),两者都运行相同的JVM - Java HotSpot(TM)64位服务器VM版本11.3-b02(我第一次认为applet与客户端JVM一起运行,而桌面运行的是服务器JVM,但它似乎都与服务器JVM有关)
Of course the JVMs received in reality different parameters, but nothing major(I think):
当然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
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
独立:-Xrunjdwp:transport = dt_socket,address = 127.0.0.1:54876,suspend = y,server = n -Xmx128M -Dfile.encoding = UTF-8
Applet : max. memory = 119.314K
小程序:最大记忆= 119.314K
- Heap
- PS Eden Space : 14,592K
- PS survivor Space : 14.528K
- PS Old Gen : 87.424K
- Total : 116.544K
总计:116.544K
PS伊甸园空间:14,592K
PS幸存者空间:14.528K
PS老一代:87.424K总计:116.544K
- Non-Heap
- Mem Pool Code Cache : 49.152K
- Mem Pool PS Perm Gen : 86.016K
- Total : 135.168K
总计:135.168K
内存池代码缓存:49.152K
Mem Pool PS Perm Gen:86.016K总计:135.168K
堆PS伊甸园空间:14,592K PS幸存者空间:14.528K PS老将:87.424K总计:116.544K
非堆Mem池代码缓存:49.152K Mem Pool PS Perm Gen:86.016K总计:135.168K
Desktop : max. memory = 129.302K
桌面:最大记忆= 129.302K
- Heap
- PS Eden Space : 8.704K
- PS survivor Space : 3.008K
- PS Old Gen : 116.544K
- Total : 126.272K
总计:126.272K
PS伊甸园空间:8.704K
PS幸存者空间:3.008K
PS老一代:116.544K总计:126.272K
- Non-Heap
- Mem Pool Code Cache : 49.152K
- Mem Pool PS Perm Gen : 65.536K
- Total : 135.168K
总计:135.168K
内存池代码缓存:49.152K
Mem Pool PS Perm Gen:65.536K总计:135.168K
堆PS伊甸园空间:8.704K PS幸存者空间:3.008K PS老将:116.544K总计:126.272K
非堆Mem池代码缓存:49.152K Mem Pool PS Perm Gen:65.536K总计:135.168K
The big differences between those two JVMs
这两个JVM之间的巨大差异
- PS Perm Gen, the applet got a bigger chunk - which makes sense since the applet will load probably additional classes compared with the standalone version(but even in this case "Old Gen" is much smaller, which is odd because usually all those additional classes will eventually get in the "Old Gen")
- Heap memory, totally different ratio between Eden/Survivor/Old Gen. Applet's Old Gen is 75% of the standalone's Old Gen, it's a big difference I would say, I'm kind if expecting (olmost) the same memory model since there shouldn't be any difference when I'm running the application as an applet or as a desktop application.
PS Perm Gen,小程序有一个更大的块 - 这是有道理的,因为applet将加载可能额外的类与独立版本相比(但即使在这种情况下“Old Gen”要小得多,这很奇怪,因为通常所有这些额外的类最终会进入“老一代”)
堆内存,Eden / Survivor / Old Gen.Applet的Old Gen之间完全不同的比例是独立的Old Gen的75%,这是一个很大的不同我会说,如果期待(olmost)相同的内存模型,我很善良,因为那里不应该当我将应用程序作为applet或桌面应用程序运行时,会有什么不同。
Now I'm even more confused, not only that I don't know how to calculate the max.memory ratio(indeed 0.9 could not be valid with future JVM versions) but my application could get out of memory when runs as an applet. I would need to increase maximum memory with ~10-15% when it runs as an applet just to be safe.
现在我更加困惑,不仅仅是我不知道如何计算max.memory比率(事实上0.9对未来的JVM版本无效),但是我的应用程序在作为applet运行时可能会内存不足。为了安全起见,当它作为小程序运行时,我需要增加大约10-15%的最大内存。
I'm still not convinced why such a different heap ratio(on the same machine) and a smaller heap(especially considering that an applet needs additional classes).
我仍然不相信为什么这样一个不同的堆比率(在同一台机器上)和一个较小的堆(特别是考虑到applet需要额外的类)。
Any reasons why? I'm curios now, this went beyond my need to check if the applet has the maximum amount of memory that I think it should.
有什么原因吗?我现在很好奇,这超出了我需要检查applet是否具有我认为应该的最大内存量。
#1
Time for a spiel on Java memory.
Java内存上的时间。
First, running out of memory in Java (ie. actually getting an OutOfMemoryError) is influenced by the peculiarities of the GC that's running.
首先,Java中的内存不足(即实际获得OutOfMemoryError)受到正在运行的GC的特性的影响。
Contrary to what the name implies, you can get an OutOfMemoryError without actually running out of memory; its also thrown when the runtime decides its spending an inordiate amount of time GC'ing (source, its buried in there).
与名称所暗示的相反,您可以获得OutOfMemoryError而不会实际耗尽内存;它也会在运行时决定花费大量时间GC(源,它埋在那里)时抛出。
Additionally, you can get an OutOfMemoryError by running out of specific kinds of memory. Remember that the Java GC is a generational collector, and if you happen to exhaust one of the generations (I want to say the "tenured" one, but I could be wrong) you're also effectively out of memory. This means you can have heap space left from the OS view, but be unable to allocate anything on the Java heap.
此外,您可以通过耗尽特定类型的内存来获取OutOfMemoryError。请记住,Java GC是一代分类收集器,如果你碰巧耗尽了其中一代(我想说“终身”一代,但我可能错了)你也有效地失去记忆。这意味着您可以从OS视图中留下堆空间,但无法在Java堆上分配任何内容。
Finally, there's some actual overhead associated with the GC that could be eating up some heap space.
最后,与GC相关的一些实际开销可能占用了一些堆空间。
What's more likely to be happening in your case, is some variant on the following: your code runs in both a standalone and an applet context, each context has a different security manager and a different startup behavior; this implies that a different set of classes (which get knocked into the permanent generation) are involved, with different dependencies. I'd guess that the applet "stack" is thicker given the more strigent constraints on their behaviors, and that probably accounts for most of the difference in maxMemory().
在您的情况下更有可能发生的是以下变体:您的代码在独立和小程序上下文中运行,每个上下文都有不同的安全管理器和不同的启动行为;这意味着涉及一组不同的类(它们被敲入永久代),具有不同的依赖性。我认为applet“stack”更厚,因为它们的行为受到更严格的限制,这可能是maxMemory()中差异的主要原因。
In short, the difference in available memory is probably due to some change in memory reserved by the Java runtime for its own operation. This could be GC related, security policy related, or just the different classes loaded for the Applet environment vs. the standalone one. Runtime.maxMemory() may also take any of the above "out of memory" conditions into account when determining what to return. Accordingly the 0.9 value is probably an implementation side-effect, one which may change in the future.
简而言之,可用内存的差异可能是由于Java运行时为其自身操作保留的内存的一些变化。这可能与GC相关,与安全策略相关,或者只是为Applet环境加载的不同类与独立类加载。在确定返回什么时,Runtime.maxMemory()也可以考虑上述任何“内存不足”条件。因此,0.9值可能是实施副作用,可能在将来发生变化。
#2
Kevin, indeed it makes sense to be a difference between how an applet runs compared with a desktop application, but what struck me is that there is a big difference in maximum(bigger that I thought) memory available between an applet and a desktop application, which is ~8%.If it is as you said "applet "stack" is thicker given the more strigent constraints on their behaviors" I was expecting that the applet will get a bigger maximum memory and not the stand-alone version.
凯文,确实让applet与桌面应用程序的运行方式有所区别是有意义的,但让我印象深刻的是applet和桌面应用程序之间的最大内存(我认为更大)内存存在很大差异,这是〜8%。如果你说“applet”堆栈“由于对其行为的更严格限制而更厚”我期待applet将获得更大的最大内存而不是独立版本。
I took some measurements between the applet and the application. Both received the same parameters(-Xmx128M), both are running with the same JVM - Java HotSpot(TM) 64-Bit Server VM version 11.3-b02(first time I thought the applet was running with client JVM and desktop was running with server JVM, but it seems both are with server JVM)
我在applet和应用程序之间进行了一些测量。两者都接收到相同的参数(-Xmx128M),两者都运行相同的JVM - Java HotSpot(TM)64位服务器VM版本11.3-b02(我第一次认为applet与客户端JVM一起运行,而桌面运行的是服务器JVM,但它似乎都与服务器JVM有关)
Of course the JVMs received in reality different parameters, but nothing major(I think):
当然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
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
独立:-Xrunjdwp:transport = dt_socket,address = 127.0.0.1:54876,suspend = y,server = n -Xmx128M -Dfile.encoding = UTF-8
Applet : max. memory = 119.314K
小程序:最大记忆= 119.314K
- Heap
- PS Eden Space : 14,592K
- PS survivor Space : 14.528K
- PS Old Gen : 87.424K
- Total : 116.544K
总计:116.544K
PS伊甸园空间:14,592K
PS幸存者空间:14.528K
PS老一代:87.424K总计:116.544K
- Non-Heap
- Mem Pool Code Cache : 49.152K
- Mem Pool PS Perm Gen : 86.016K
- Total : 135.168K
总计:135.168K
内存池代码缓存:49.152K
Mem Pool PS Perm Gen:86.016K总计:135.168K
堆PS伊甸园空间:14,592K PS幸存者空间:14.528K PS老将:87.424K总计:116.544K
非堆Mem池代码缓存:49.152K Mem Pool PS Perm Gen:86.016K总计:135.168K
Desktop : max. memory = 129.302K
桌面:最大记忆= 129.302K
- Heap
- PS Eden Space : 8.704K
- PS survivor Space : 3.008K
- PS Old Gen : 116.544K
- Total : 126.272K
总计:126.272K
PS伊甸园空间:8.704K
PS幸存者空间:3.008K
PS老一代:116.544K总计:126.272K
- Non-Heap
- Mem Pool Code Cache : 49.152K
- Mem Pool PS Perm Gen : 65.536K
- Total : 135.168K
总计:135.168K
内存池代码缓存:49.152K
Mem Pool PS Perm Gen:65.536K总计:135.168K
堆PS伊甸园空间:8.704K PS幸存者空间:3.008K PS老将:116.544K总计:126.272K
非堆Mem池代码缓存:49.152K Mem Pool PS Perm Gen:65.536K总计:135.168K
The big differences between those two JVMs
这两个JVM之间的巨大差异
- PS Perm Gen, the applet got a bigger chunk - which makes sense since the applet will load probably additional classes compared with the standalone version(but even in this case "Old Gen" is much smaller, which is odd because usually all those additional classes will eventually get in the "Old Gen")
- Heap memory, totally different ratio between Eden/Survivor/Old Gen. Applet's Old Gen is 75% of the standalone's Old Gen, it's a big difference I would say, I'm kind if expecting (olmost) the same memory model since there shouldn't be any difference when I'm running the application as an applet or as a desktop application.
PS Perm Gen,小程序有一个更大的块 - 这是有道理的,因为applet将加载可能额外的类与独立版本相比(但即使在这种情况下“Old Gen”要小得多,这很奇怪,因为通常所有这些额外的类最终会进入“老一代”)
堆内存,Eden / Survivor / Old Gen.Applet的Old Gen之间完全不同的比例是独立的Old Gen的75%,这是一个很大的不同我会说,如果期待(olmost)相同的内存模型,我很善良,因为那里不应该当我将应用程序作为applet或桌面应用程序运行时,会有什么不同。
Now I'm even more confused, not only that I don't know how to calculate the max.memory ratio(indeed 0.9 could not be valid with future JVM versions) but my application could get out of memory when runs as an applet. I would need to increase maximum memory with ~10-15% when it runs as an applet just to be safe.
现在我更加困惑,不仅仅是我不知道如何计算max.memory比率(事实上0.9对未来的JVM版本无效),但是我的应用程序在作为applet运行时可能会内存不足。为了安全起见,当它作为小程序运行时,我需要增加大约10-15%的最大内存。
I'm still not convinced why such a different heap ratio(on the same machine) and a smaller heap(especially considering that an applet needs additional classes).
我仍然不相信为什么这样一个不同的堆比率(在同一台机器上)和一个较小的堆(特别是考虑到applet需要额外的类)。
Any reasons why? I'm curios now, this went beyond my need to check if the applet has the maximum amount of memory that I think it should.
有什么原因吗?我现在很好奇,这超出了我需要检查applet是否具有我认为应该的最大内存量。