JDK-8068162 : jvmtiRedefineClasses.cpp: guarantee(false) failed: OLD and/or OBSOLETE method(s) found
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 8u91,8u101,9
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2014-12-23
  • Updated: 2016-04-27
  • Resolved: 2015-01-27
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 8 JDK 9
8u101Fixed 9 b50Fixed
Related Reports
Relates :  
Sub Tasks
JDK-8068242 :  
Description
----------messages:(3/211)----------
command: main -javaagent:IsModifiableClassAgent.jar IsModifiableClassApp
reason: User specified action: run main/othervm -javaagent:IsModifiableClassAgent.jar IsModifiableClassApp 
elapsed time (seconds): 1.923
----------System.out:(22/1356)----------
IsModifiableClassAgent started
INFO: use the '-XX:TraceRedefineClasses=16384' option to see more info about the following guarantee() failure.
# To suppress the following error report, specify this argument
# after -XX: or in .hotspotrc:  SuppressErrorAt=/jvmtiRedefineClasses.cpp:4208
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/opt/jprt/T/P1/071024.yqi/s/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp:4208), pid=26090, tid=3717565296
#  guarantee(false) failed: OLD and/or OBSOLETE method(s) found
#
# JRE version: Java(TM) SE Runtime Environment (9.0) (build 1.9.0-internal-fastdebug-20141220071024.yqi.hs-rt-b00)
# Java VM: Java HotSpot(TM) Client VM (1.9.0-internal-fastdebug-20141220071024.yqi.hs-rt-b00 compiled mode linux-x86 )
# Core dump written. Default location: Core dumps may be processed with "/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e" (or dumping to /export/local/aurora/sandbox/results/workDir/java/lang/instrument/IsModifiableClassAgent/core.26090)
#
# An error report file with more information is saved as:
# /export/local/aurora/sandbox/results/workDir/java/lang/instrument/IsModifiableClassAgent/hs_err_pid26090.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
Current thread is 3717565296
Dumping core ...
Comments
Thanks, guys! It has to be Ok then. There is no entry for this test in the jdk/test/ProblemList.txt.
04-02-2015

Since this test is in the 'jdk' repo: java/lang/instrument/IsModifiableClassAgent.java there are two mechanisms that work for keeping the test from running: - @ignore in the test itself - an entry in the jdk/test/ProblemList.txt When you want to enable a test, you need to check both.
04-02-2015

Yes, taking out @ignore does it. I didn't see this before.
04-02-2015

[to Coleen] I thought, it is enough to remove "ignore" tag in the test as it is in my patch: URL: http://hg.openjdk.java.net/jdk9/hs-rt/jdk/rev/0d0ee1a20b17
03-02-2015

I think you have to unquarantine the test IsModifiableClassAgent.java now.
03-02-2015

The updated webrev with the suggested fix: http://cr.openjdk.java.net/~sspitsyn/webrevs/2015/hotspot/8068162-JVMTI-old.4/
24-01-2015

I see. We don't adjust all the itables, only ones for classes that are subclasses of the redefined class. // If the current class has an itable and we are either redefining an // interface or if the current class is a subclass of the_class, then // we potentially have to fix the itable. If we are redefining an // interface, then we have to call adjust_method_entries() for // every InstanceKlass that has an itable since there isn't a // subclass relationship between an interface and an InstanceKlass. if (ik->itable_length() > 0 && (_the_class_oop->is_interface() || ik->is_subclass_of(_the_class_oop))) { // ik->itable() creates a wrapper object; rm cleans it up ResourceMark rm(_thread); ik->itable()->adjust_method_entries(_matching_old_methods, _matching_new_methods, _matching_methods_length, &trace_name_printed); }
31-12-2014

Ok, thanks! It is not updated in adjust_method_entries because the Unsafe::throw_illegal_access is added to other itables. You are right, my fix is not good. We have to replace the method pointers when the Unsafe is redefined, not when the classes with the related itable entries are redefined.
31-12-2014

I think so, yes. From the webrev, why isn't the replacement in adjust_method_entries? How did it miss Unsafe::throw_illegal_access there? When the Unsafe class is retransformed, isn't there a new version of this function?
31-12-2014

A question: Do we expect the same issue to appear in the JDK 8 as well?
31-12-2014

The suggested fix is in the pen webrev: http://cr.openjdk.java.net/~sspitsyn/webrevs/2014/hotspot/8068162-JVMTI-old.1/
31-12-2014

Yes, the addClass uses the class LatestMethodCache. Using the class LatestMethodCache solves only a part of the task. In fact the Method* pointers in the itable must be updated to the latest (retransformed) version of throwIllegalAccessError(). I'll send my webrev for review shortly.
31-12-2014

Forgot to share my findings... The interface method lambda$chars$0()Ljava/util/Spliterator$OfInt in two classes has no default method defined: MY_TRACE: init_itable_for_interface: method: lambda$chars$0()Ljava/util/Spliterator$OfInt;, class: java/nio/CharBuffer MY_TRACE: init_itable_for_interface: method: lambda$chars$0()Ljava/util/Spliterator$OfInt;, class: java/nio/HeapCharBuffer The two classes above are generated at build time.
30-12-2014

I think the new JDK code might have an illegal access method for a default method in the itable for some situation. To fix this use the same thing as addClass. It uses the method_idnum instead of Method*.
30-12-2014

[to Coleen] Sorry, I incorrectly told that the method was deleted. The throwIllegalAccessError() becomes old after the class Unsafe is retransformed. You are right, the problem is that the Method* is cached in the memory/universe.cpp. I'll check how to fix this. I'm still not sure what triggered the regression to appear in the nightly. One possible reason can be because the test was quarantined before.
30-12-2014

Is it deleted or do we only refer to the old method? In memory/universe.cpp we cache the Method* to add to the itable which is wrong. It should use the trick that java.lang.ClassLoader.addClass and a couple of other methods use. I thought it did but just noticed it's wrong today.
30-12-2014

The method throwIllegalAccessError is added to the itable, not vtable and then it gets magically deleted at retransformation.
29-12-2014

This is the function that David Chase adds to the vtable directly for default methods. Maybe there is a direct pointer in the JVM and it doesn't use a method_id like java/lang/ClassLoader.addClass.
27-12-2014

It seems this regression really came with the changes on the jdk side. I've added some tracing and got this line many times: klassItable::check_no_old_or_obsolete_entries: class: Lsun/misc/Unsafe;, method: throwIllegalAccessError()V This is a definition of the private static method throwIllegalAccessError() in the class sun.misc.Unsafe: /** * Throws IllegalAccessError; for use by the VM. * @since 1.8 */ private static void throwIllegalAccessError() { throw new IllegalAccessError(); } Now, I'm puzzled with the fact that the throwIllegalAccessError() gets somehow deleted. The java-agent IsModifiableClassAgent does not delete methods from a class being re-transformed.
25-12-2014

I'm puzzled with the above investigation. The problem is that it seems the issue was introduced by the integration into jdk9/hs: http://scaaa637.us.oracle.com/archive/integrations/jdk9/hs/2014-12-20-010712.amurillo.jdk9-hs2-2014-12-19-snapshot/ However, I do not see any hotspot fixes in that integration. It looks very strange to me because the bug is hotspot specific. It is hard to imaging how this kind of issue can be introduced on the jdk side. The only area to look at are any top-level or build-related changes.
24-12-2014

The regression came to the hs-rt from the integration: http://scaaa637.us.oracle.com/archive/integrations/jdk9/hs-rt/2014-12-20-071024.yqi.hs-rt/ The regression came to the hs-gc from the integration: http://scaaa637.us.oracle.com/archive/integrations/jdk9/hs-gc/2014-12-22-162758.jesper.jdk9-main/ The regression came to the hs-comp from the integration: http://scaaa637.us.oracle.com/archive/integrations/jdk9/hs-comp/2014-12-22-223836.vkozlov.main_to_comp/ The regression came to the hs-emb from the integration: http://scaaa637.us.oracle.com/archive/integrations/jdk9/hs-emb/2014-12-20-021613.amurillo.jdk9-hs2-2014-12-19-emb-sync/ The regression came to the hs from the integration: http://scaaa637.us.oracle.com/archive/integrations/jdk9/hs/2014-12-20-010712.amurillo.jdk9-hs2-2014-12-19-snapshot/ The jdk9/dev does not have this regression yet, the latest integration is: http://scaaa637.us.oracle.com/archive/integrations/jdk9/dev/2014-11-03-005453.daholme.jdk9-dev/ The 2014-12-20-010712.amurillo.jdk9-hs2-2014-12-19-snapshot has 115 changesets from different source-trees.
24-12-2014

[to Dmitry S.] I'm looking at this issue. It is interesting to understand why we've got this regression now. I'll try to isolate the build caused it. I don't know how to quarantine the test yet but hope it is not a problem in general. [to Alexander K.] This issue does not assert fundamental aspects of Java. :) In opposite, it is very specific even for debugging and profiling. I think, it is Ok to quarantine the test as this issue normally does not hit users.
23-12-2014

It is strange that the build in the nightly is shown as b0: Java(TM) SE Runtime Environment 1.9.0 b0 (1.9.0-internal-fastdebug-20141220071024.yqi.hs-rt-b00)
23-12-2014

It looks like the old fixed bug has been returned: https://bugs.openjdk.java.net/browse/JDK-8042796 Interesting why it has been appeared only now.
23-12-2014