JDK-7024561 : JSR 292 constant pool cache _f1 field doesn't get properly updated with parallel GC
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs21
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2011-03-04
  • Updated: 2011-04-07
  • Resolved: 2011-04-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Duplicate :  
Relates :  
Description
A testcase Remi Forax posted on mlvm-dev:

http://mail.openjdk.java.net/pipermail/mlvm-dev/2011-March/002555.html

shows a problem with JSR 292 and parallel GC.

Comments
EVALUATION Fixed as part of this bug, which had a similar requirement to scavenge the constant pool cache: 7017732: move static fields into Class to prepare for perm gen removal
07-04-2011

SUGGESTED FIX diff --git a/src/share/vm/oops/cpCacheKlass.cpp b/src/share/vm/oops/cpCacheKlass.cpp --- a/src/share/vm/oops/cpCacheKlass.cpp +++ b/src/share/vm/oops/cpCacheKlass.cpp @@ -173,11 +173,11 @@ // during a scavenge, it is safe to inspect my pool, since it is perm constantPoolOop pool = cache->constant_pool(); assert(pool->is_constantPool(), "should be constant pool"); - if (pool->has_invokedynamic()) { + if (true) { for (int i = 0; i < cache->length(); i++) { ConstantPoolCacheEntry* e = cache->entry_at(i); oop* p = (oop*)&e->_f1; - if (e->is_secondary_entry()) { + if (true) { if (PSScavenge::should_scavenge(p)) pm->claim_or_forward_depth(p); assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)), Also, remove the has_invokedynamic and set_invokedynamic methods, if this is the sole use of them outside of printing code.
30-03-2011

EVALUATION This is bug-tail from 6984311. The problem experienced by the customer appears to be with CONSTANT_MethodHandle entries representing BSMs. The routine constantPoolOopDesc::resolve_constant_at_impl call set_f1 to store a resolved constant into a CP cache. The constant oops stored there will, in general, fail to be scavenged. Before 6984311, the only scavengeable oops stored in _f1 were CallSite pointers put there by ConstantPoolCacheEntry::set_dynamic_call. In that particular case, the gating in constantPoolCacheKlass::oop_push_contents would allow all such CallSite pointers to be scavenged as necessary. The gating is on (a) the presence of resolved invokedynamic instructions, and (b) on the _f1 being in a "secondary" (CallSite) CP cache entry. After 6984311, other scavengeable oops are stored in various _f1 entries. Therefore, the fix to this bug is to remove the guards in constantPoolCacheKlass::oop_push_contents. See Suggested Fix.
30-03-2011

EVALUATION This works with UseSerialGC but fails with UseParallelGC. $ gamma -XX:+UseParallelGC -XX:+TraceMethodHandles -XX:+PrintGC -XX:+PrintMiscellaneous -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp . Megamorphic2 ... resolving bootstrap method for 0xb65daf98 at 2 at cache[18]CP[143]... result_oop: e4e51720 sun.dyn.DirectMethodHandle - klass: 'sun/dyn/DirectMethodHandle' - ---- fields (total size 6 words): - private 'vmentry' 'I' @8 -93565868 (fa6c4c54) - protected 'vmtarget' 'Ljava/lang/Object;' @12 {method} 'staticBootstrap' '(Ljava/dyn/MethodHandles$Lookup;Ljava/lang/String;Ljava/dyn/MethodType;[Ljava/lang/Object;)Ljava/dyn/CallSite;' in 'jsr335/lambda/optimizer/RT' (b65f2738) - private 'type' 'Ljava/dyn/MethodType;' @16 a 'java/dyn/MethodType' = (Ljava/dyn/MethodHandles$Lookup;Ljava/lang/String;Ljava/dyn/MethodType;[Ljava/lang/Object;)Ljava/dyn/CallSite; (e4e50f00) - private final 'vmindex' 'I' @20 -2 (fffffffe) bootstrap method for 0xb65daf98 at 2 retrieved as 0xe4e51720: ... [GC 16896K->5180K(62720K), 0.1407775 secs] [GC 22076K->6300K(79616K), 0.1852707 secs] [GC 40092K->8564K(81152K), 0.5988057 secs] [GC 43892K->11040K(113920K), 0.7261760 secs] [GC 79136K->15784K(113920K), 1.1371119 secs] [GC 83880K->20608K(188224K), 1.0771812 secs] resolving bootstrap method for 0xb65daf98 at 9 at cache[18]CP[143]... result_oop: e4e51720 [Ljava.lang.Object; - klass: 'java/lang/Object'[] - length: 1 - 0 : "foo" bootstrap method for 0xb65daf98 at 9 retrieved as 0xe4e51720: Exception in thread "main" java.lang.IllegalStateException: no bootstrap method found for invokedynamic at Megamorphic2.test(Megamorphic2.java:60) at Megamorphic2.main(Megamorphic2.java:52) The first time result_oop points to the correct BSM but later, after a couple of GC cycles, the pointer value is still the same but the Java heap object behind it has changed. It's purely random if there is a valid object or it points to some other memory, which may result in an assert: # Internal Error (/home/twisti/hotspot-comp/hotspot/src/share/vm/classfile/systemDictionary.cpp:2585), pid=10916, tid=2 # assert(bsm_oop->is_oop()) failed: must be sane
04-03-2011