|
Quick Lists
|
|
Bug ID:
|
6595845
|
|
Votes
|
8
|
|
Synopsis
|
Java 6 JavaWebstart increases footprint by factor 2
|
|
Category
|
javawebstart:general
|
|
Reported Against
|
b06
|
|
Release Fixed
|
,
6u10(b13) (Bug ID:2158703)
, 6u6(b01) (Bug ID:2159626)
|
|
State
|
6-Fix Understood,
bug
|
|
Priority:
|
1-Very High
|
|
Related Bugs
|
6566201
,
6654121
,
6661861
,
6673890
,
6678289
,
6709297
,
6741349
,
6786318
,
6226269
|
|
Submit Date
|
22-AUG-2007
|
|
Description
|
Customer reported that using JWS 6u1 increases footprint of their
application by factor 2.
The application was only started up and some initial but identical
functions were called.
Customer used the following setup:
Application AgreeBAP 3.2 (customer's application)
JRE 6u1
When using JWS 6u1 on JRE 6u1 (default) to load the application, we have the
following Java objects' footprint:
#instances #bytes
Total 1988354 107676864
When using (as a diagnostic test) JWS 1.4.2_11 on JRE 6u1 to load the application,
we have the following Java objects' footprint:
#instances #bytes
Total 825587 51769992
Please note that in both cases JWS was running on JRE 6u1. So the only
component that varied was JWS. Customer's application remained unchanged
as well.
Memory consumption of the application changed like follows:
< totalMemory=62316544bytes \= 59,430MB
< freeMemory=26646976bytes \= 25,413MB
---
> totalMemory=133234688bytes \= 127,062MB
> freeMemory=41470472bytes \= 39,549MB
Looking into histograms gives:
num #instances #bytes class name num #instances #bytes class name
-------------------------------------- --------------------------------------
1: 131730 13009576 [C | 1: 364708 40070096 [C
2: 42319 4807904 <constMethodKlass> | 2: 105221 9778616 [Ljava.util.HashMap$Entry
3: 9150 3647584 [I | 3: 366263 8790312 java.lang.String
4: 42319 3387056 <methodKlass> | 4: 318200 7636800 java.util.HashMap$Entry
5: 134691 3232584 java.lang.String | 5: 7434 5809336 [B
6: 70516 2753528 <symbolKlass> | 6: 39657 4583280 <constMethodKlass>
7: 5273 2592840 [B | 7: 105166 4206640 java.util.HashMap
8: 4117 2293992 <constantPoolKlass> | 8: 39657 3173696 <methodKlass>
9: 4117 1985904 <instanceKlassKlass> | 9: 109248 2701384 [I
10: 3496 1294448 <constantPoolCacheKlass> | 10: 69414 2699248 <symbolKlass>
11: 50941 1222584 java.util.HashMap$Entry | 11: 3861 2218800 <constantPoolKlass>
12: 23546 1075024 [Ljava.util.HashMap$Entry; | 12: 3861 1885528 <instanceKlassKlass>
13: 39960 959040 java.util.Hashtable$Entry | 13: 104183 1666928 java.util.jar.Attributes$Name
14: 23519 940760 java.util.HashMap | 14: 98296 1572736 java.util.jar.Attributes
15: 12709 622184 [Ljava.lang.Object; | 15: 3272 1230960 <constantPoolCacheKlass>
16: 5379 511920 [S | 16: 15275 1222000 java.lang.reflect.Method
17: 4661 447456 java.lang.Class | 17: 15480 710176 [Ljava.lang.Object;
18: 1392 389232 [Ljava.util.Hashtable$Entry; | 18: 5056 498856 [S
19: 11216 358912 java.lang.ref.SoftReference | 19: 4369 419424 java.lang.Class
20: 4221 337680 java.lang.reflect.Method | 20: 10743 343776 java.lang.ref.SoftReference
21: 20440 327040 java.util.jar.Attributes$Name | 21: 2895 324960 [Ljava.lang.String;
22: 2676 317856 [Ljava.lang.String; | 22: 12283 294792 java.lang.ref.WeakReference
23: 7043 299472 [[I | 23: 6539 279400 [[I
24: 12326 295824 java.lang.ref.WeakReference | 24: 3782 242048 java.beans.PropertyDescriptor
25: 18452 295232 java.util.jar.Attributes | 25: 14509 232144 java.util.HashMap$EntrySet
26: 18423 294768 java.util.HashMap$EntrySet | 26: 7949 190776 java.util.LinkedList$Entry
27: 3782 242048 java.beans.PropertyDescriptor | 27: 7778 186672 java.util.Hashtable$Entry
28: 535 171200 <objArrayKlassKlass> | 28: 499 159680 <objArrayKlassKlass>
[ ... ]
Total 825587 51769992 | Total 1988354 107676864
So, we have a threefold incease of objects of type [C : this account for 25 MB increase alone.
1: 131730 13009576 [C | 1: 364708 40070096 [C
a nearly threefold increase for objects of java.lang.String :
5: 134691 3232584 java.lang.String | 3: 366263 8790312 java.lang.String
a sixfold increase for objects of java.util.HashMap$Entry:
11: 50941 1222584 java.util.HashMap$Entry | 4: 318200 7636800 java.util.HashMap$Entry
a fourfold increase in for objects of [Ljava.util.HashMap$Entry :
12: 23546 1075024 [Ljava.util.HashMap$Entry; | 2: 105221 9778616 [Ljava.util.HashMap$Entry
however a nearly fivefold decrease for objects of java.util.Hashtable$Entry :
13: 39960 959040 java.util.Hashtable$Entry 27: 7778 186672 java.util.Hashtable$Entry
Posted Date : 2007-08-22 13:22:52.0
Identical bahviour was confirmed for Java 6u2.
Posted Date : 2007-08-23 07:51:08.0
|
|
Work Around
|
N/A
|
|
Evaluation
|
For customer application memory consumption is as follows:
BAP 3.10-14 b4GC afterGC
----------------------------------------------------------
Heap Perm Heap Perm
----------------------------------------------------------
14211 on JRE 16004 28-30 15.4 21.6 15.0
16004 122-124 16.5 82.4 16.0
16010b411 114-132 16.4 110.3 16.0
Investigation shows that most of additional space is taken by
CachedJarFile (in particular Manifest and signerMap).
Experiments with replacing reference to ImmutableManifest with
weak reference confirms this idea:
16010b411+deploy.jar 65-130 16.5 49.7 16.0
Memory consumption decreases from 110.3 to 49.7, i.e. by 60Mb.
Difference between 6u10 and 6u4 seems to be explained by introduction of
ImmutableManifests (see 6566201) that seems to mistakenly keep 2 copies of manifest
(because ImmutableManifest constructor calls super(mf) that creates clone of manifest
and this copy is never used). Given that 60Mb is needed for manifest objects,
extra copy should cost about 30Mb and this is very close to observed difference
between 6u4 and 6u10. Avoiding duplicate copies peak memory consumption should decrease
(and it should have possitive impact on performance).
From heap dump it seems that keeping weak references to signerMap may help to
reduce footprint by another 20Mb. This has to be verified yet.
Also, from code inspection it seems that we probably can keep immutable manifest as part of CacheEntry unless there is a reason to alter these manifests. And we probably do not need to clone signersMap too before creating immutable collection.
The downside of it is that manifest and signers might need to be reconstructed if they will be needed later and this may have impact on performance.
Posted Date : 2008-01-16 10:18:46.0
Further changes:
1) I've changed J2SE code (ZipFile) a bit to release unneeded buffers.
Measurement shown that there were 6M in these buffers for this particular application.
2) Most of CacheEntry content is now softly referenced.
This helps to release memory if these entries are not really used.
3) Reworked memory part of cache.
It did not seem to work well because only one reference was saved
and resource was considered as unused as soon as it was released.
This cause extra reloads and also together with my changes it made things fragile.
(Because we may need to restore data after long idle time
and if resource was considered unused it could have been removed).
Moved memory related logic to separate class (MemoryCache),
trying to create phantom reference every time new copy of resource
is getting used and releasing resource only after reference counter gets to 0.
Added yet another cleanup thread for this.
4) Replaced ImmutableManifest with transforming manifest to read only in place using reflection and Collections.
This saves some memory but it has a drawback. Attempt to modify read-only Manifest will now throw UnsupportedOperationException.
5) Updated CachedJarFile14 similarly to CachedJarFile
Test results are promising. Better footprint and performance than 1.4.2.
Here are details:
-------------
BAP 3.10-14 Heap b4GC afterGC
--------------------------------------
14211 on JRE 16004 28-32 21.7
16004 117-125 90.0
16010 103-106 14.7
2. Finding minimum heap amount
-------------------------------------------------
Tests showed that the application starts fine with no noticeable
performance impact with a max of 15MB. The application itself
needs 14.7 MB. Download still works fine with a max of 10MB
with no performance impact, but the application then fails to
initialize. This shows that Web Start now needs less than 10 MB,
while it used to require more than 90 MB before the optimizations,
and still about 70 MB in the last tests.
Performance:
Web Start App download time
[min:sec] Web Start 1.4.2_11 on JRE 1.6.0_04
max-heap=128M: 6:20
Web Start 1.6.0_04 on JRE 1.6.0_04
max-heap=128M: 6:07
Web Start 1.6.0_10 on JRE 1.6.0_10
max-heap=128M: 5:59
max-heap=75M: 6:02
max-heap=70M: 6:03
max-heap=65M: 6:01
max-heap=55M: 6:05
max-heap=45M: 6:03
max-heap=35M: 6:04
max-heap=25M: 6:04
max-heap=20M: 6:07
max-heap=15M: 6:06
max-heap=10M: 6:09
Posted Date : 2008-02-01 15:04:38.0
Changes reduce footprint for other webstart applications and applets too but not that dramatically. E.g. for bugster at login screen:
6u3 - 5.5Mb
fixed 6u10 - 3.6Mb
Posted Date : 2008-02-11 23:25:20.0
|
|
Comments
|
Submitted On 26-SEP-2007
I'm facing the same problem. When I start the exact same application using jre1.6.0_02 the amount of memory is multiplied by 3 according to jre1.5.0_12!
In my JNLP file I specified the exact j2se version:
<j2se version="1.4.2_09"/>
So the only difference between the two tests seems to be the JWS implementation that starts the application!
Submitted On 03-SEP-2008
rossjudson
Note that during initialization of a large signed application through webstart, garbage collection can and will cause the weak references to be cleared, causing the following NullPointerException. Settings the JNLP startup flags to include "-Xms256m" provides enough memory that the weak references are not cleared during startup.
java.lang.NullPointerException
at com.sun.javaws.security.SigningInfo.verifyAllEntriesSigned(Unknown Source)
at com.sun.javaws.security.SigningInfo.checkSigning(Unknown Source)
at com.sun.javaws.LaunchDownload.checkSignedResourcesHelper(Unknown Source)
at com.sun.javaws.LaunchDownload.checkSignedResources(Unknown Source)
at com.sun.javaws.Launcher.prepareLaunchFile(Unknown Source)
at com.sun.javaws.Launcher.prepareToLaunch(Unknown Source)
at com.sun.javaws.Launcher.launch(Unknown Source)
at com.sun.javaws.Main.launchApp(Unknown Source)
at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
at com.sun.javaws.Main$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|
|
|
 |