Re: RFR: 8277072: ObjectStreamClass caches keep ClassLoaders alive [v4]

2021-12-04 Thread Peter Levart
On Thu, 2 Dec 2021 14:24:06 GMT, Roman Kennke  wrote:

>> src/java.base/share/classes/java/io/ObjectStreamClass.java line 2133:
>> 
>>> 2131: if (oldReflector != null) {
>>> 2132: reflector = oldReflector;
>>> 2133: }
>> 
>> Map.computeIfAbsent(key, () -> new FieldReflector(matchFields, localDesc));
>> might be more compact.
>
> That would be nicer, indeed. Problem is that matchFields throws an 
> InvalidClassException, and that would have to get passed through the lambda.
> Also, that problem is pre-existing and not related to the change.

Yes, I did computeIfAbsent() originally just to find out handling check 
exception/wrapping/unwrapping would make the code much more complex.

-

PR: https://git.openjdk.java.net/jdk/pull/6375


Re: RFR: 8277072: ObjectStreamClass caches keep ClassLoaders alive [v4]

2021-12-02 Thread Roman Kennke
On Wed, 1 Dec 2021 21:09:14 GMT, Roger Riggs  wrote:

> Without the use of SoftReference, memory pressure won't release any of the 
> cached info. That seems to swing the other way from overly aggressively 
> freeing memory with the WeakReference (and needing to recompute) as the 
> change originally proposed. Its hard to tell in what environments it might be 
> observed.

Right. The problem with the original code was that the softreference would keep 
the class from getting unloaded, except when under pressure. Now that the 
cached value is tied to the object lifetime using ClassValue, we can relatively 
easily use SoftReference to also make it sensitive to memory pressure. I 
factored this code out into its own class to avoid making a mess, and to be 
able to reuse it in subclassAudits (see #6637).

> src/java.base/share/classes/java/io/ObjectStreamClass.java line 2133:
> 
>> 2131: if (oldReflector != null) {
>> 2132: reflector = oldReflector;
>> 2133: }
> 
> Map.computeIfAbsent(key, () -> new FieldReflector(matchFields, localDesc));
> might be more compact.

That would be nicer, indeed. Problem is that matchFields throws an 
InvalidClassException, and that would have to get passed through the lambda.
Also, that problem is pre-existing and not related to the change.

> test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java line 52:
> 
>> 50: Class loadClass = 
>> myOwnClassLoader.loadClass("ObjectStreamClass_MemoryLeakExample");
>> 51: Constructor con = loadClass.getConstructor();
>> 52: con.setAccessible(true);
> 
> Isn't the constructor already public?

> 
Yes, but:

test TestOSCClassLoaderLeak.run(): failure
java.lang.IllegalAccessException: class TestOSCClassLoaderLeak cannot access a 
member of class ObjectStreamClass_MemoryLeakExample with modifiers "public"

-

PR: https://git.openjdk.java.net/jdk/pull/6375


Re: RFR: 8277072: ObjectStreamClass caches keep ClassLoaders alive [v4]

2021-12-01 Thread Roger Riggs
On Wed, 1 Dec 2021 12:18:05 GMT, Roman Kennke  wrote:

>> The caches in ObjectStreamClass basically map WeakReference to 
>> SoftReference, where the ObjectStreamClass also 
>> references the same Class. That means that the cache entry, and thus the 
>> class and its class-loader, will not get reclaimed, unless the GC determines 
>> that memory pressure is very high.
>> 
>> However, this seems bogus, because that unnecessarily keeps ClassLoaders and 
>> all its classes alive much longer than necessary: as soon as a ClassLoader 
>> (and all its classes) become unreachable, there is no point in retaining the 
>> stuff in OSC's caches.
>> 
>> The proposed change is to use WeakReference instead of SoftReference for the 
>> values in caches.
>> 
>> Testing:
>>  - [x] tier1
>>  - [x] tier2
>>  - [x] tier3
>>  - [ ] tier4
>
> Roman Kennke has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Remove unused EntryFuture inner class from ObjectSteamClass

Without the use of SoftReference, memory pressure won't release any of the 
cached info.
That seems to swing the other way from overly aggressively freeing memory with 
the WeakReference (and needing to recompute) as the change originally proposed. 
 
Its hard to tell in what environments it might be observed.

src/java.base/share/classes/java/io/ObjectStreamClass.java line 2133:

> 2131: if (oldReflector != null) {
> 2132: reflector = oldReflector;
> 2133: }

Map.computeIfAbsent(key, () -> new FieldReflector(matchFields, localDesc));
might be more compact.

test/jdk/java/io/ObjectStreamClass/TestOSCClassLoaderLeak.java line 52:

> 50: Class loadClass = 
> myOwnClassLoader.loadClass("ObjectStreamClass_MemoryLeakExample");
> 51: Constructor con = loadClass.getConstructor();
> 52: con.setAccessible(true);

Isn't the constructor already public?

-

PR: https://git.openjdk.java.net/jdk/pull/6375


Re: RFR: 8277072: ObjectStreamClass caches keep ClassLoaders alive [v4]

2021-12-01 Thread Roman Kennke
> The caches in ObjectStreamClass basically map WeakReference to 
> SoftReference, where the ObjectStreamClass also references 
> the same Class. That means that the cache entry, and thus the class and its 
> class-loader, will not get reclaimed, unless the GC determines that memory 
> pressure is very high.
> 
> However, this seems bogus, because that unnecessarily keeps ClassLoaders and 
> all its classes alive much longer than necessary: as soon as a ClassLoader 
> (and all its classes) become unreachable, there is no point in retaining the 
> stuff in OSC's caches.
> 
> The proposed change is to use WeakReference instead of SoftReference for the 
> values in caches.
> 
> Testing:
>  - [x] tier1
>  - [x] tier2
>  - [x] tier3
>  - [ ] tier4

Roman Kennke has updated the pull request incrementally with one additional 
commit since the last revision:

  Remove unused EntryFuture inner class from ObjectSteamClass

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/6375/files
  - new: https://git.openjdk.java.net/jdk/pull/6375/files/2ed745b3..b7d53adc

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=6375=03
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=6375=02-03

  Stats: 65 lines in 1 file changed: 0 ins; 65 del; 0 mod
  Patch: https://git.openjdk.java.net/jdk/pull/6375.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/6375/head:pull/6375

PR: https://git.openjdk.java.net/jdk/pull/6375