8087315: SIGBUS error in nsk/jvmti/RedefineClasses/StressRedefine
Need to get source_file_name from the_class's constant pool not previous version constant pool Reviewed-by: dcubed, sspitsyn
This commit is contained in:
parent
d7f565d9eb
commit
77edd5baad
@ -1468,6 +1468,19 @@ class BacktraceBuilder: public StackObj {
|
||||
|
||||
};
|
||||
|
||||
Symbol* get_source_file_name(InstanceKlass* holder, int version) {
|
||||
// Find the specific ik version that contains this source_file_name_index
|
||||
// via the previous versions list, but use the current version's
|
||||
// constant pool to look it up. The previous version's index has been
|
||||
// merged for the current constant pool.
|
||||
InstanceKlass* ik = holder->get_klass_version(version);
|
||||
// This version has been cleaned up.
|
||||
if (ik == NULL) return NULL;
|
||||
int source_file_name_index = ik->source_file_name_index();
|
||||
return (source_file_name_index == 0) ?
|
||||
(Symbol*)NULL : holder->constants()->symbol_at(source_file_name_index);
|
||||
}
|
||||
|
||||
// Print stack trace element to resource allocated buffer
|
||||
char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
|
||||
int method_id, int version, int bci, int cpref) {
|
||||
@ -1484,17 +1497,11 @@ char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
|
||||
char* method_name = sym->as_C_string();
|
||||
buf_len += (int)strlen(method_name);
|
||||
|
||||
// Use specific ik version as a holder since the mirror might
|
||||
// refer to version that is now obsolete and no longer accessible
|
||||
// via the previous versions list.
|
||||
holder = holder->get_klass_version(version);
|
||||
char* source_file_name = NULL;
|
||||
if (holder != NULL) {
|
||||
Symbol* source = holder->source_file_name();
|
||||
if (source != NULL) {
|
||||
source_file_name = source->as_C_string();
|
||||
buf_len += (int)strlen(source_file_name);
|
||||
}
|
||||
Symbol* source = get_source_file_name(holder, version);
|
||||
if (source != NULL) {
|
||||
source_file_name = source->as_C_string();
|
||||
buf_len += (int)strlen(source_file_name);
|
||||
}
|
||||
|
||||
// Allocate temporary buffer with extra space for formatting and line number
|
||||
@ -1909,12 +1916,7 @@ oop java_lang_StackTraceElement::create(Handle mirror, int method_id,
|
||||
java_lang_StackTraceElement::set_lineNumber(element(), -1);
|
||||
} else {
|
||||
// Fill in source file name and line number.
|
||||
// Use specific ik version as a holder since the mirror might
|
||||
// refer to version that is now obsolete and no longer accessible
|
||||
// via the previous versions list.
|
||||
holder = holder->get_klass_version(version);
|
||||
assert(holder != NULL, "sanity check");
|
||||
Symbol* source = holder->source_file_name();
|
||||
Symbol* source = get_source_file_name(holder, version);
|
||||
if (ShowHiddenFrames && source == NULL)
|
||||
source = vmSymbols::unknown_class_name();
|
||||
oop filename = StringTable::intern(source, CHECK_0);
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8087315
|
||||
* @summary Get old method's stack trace elements after GC
|
||||
* @library /testlibrary
|
||||
* @modules java.compiler
|
||||
* java.instrument
|
||||
* jdk.jartool/sun.tools.jar
|
||||
* @build RedefineClassHelper
|
||||
* @run main RedefineClassHelper
|
||||
* @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
|
||||
*/
|
||||
|
||||
import static jdk.test.lib.Asserts.*;
|
||||
|
||||
public class RedefineRunningMethodsWithBacktrace {
|
||||
|
||||
public static String newB =
|
||||
"class RedefineRunningMethodsWithBacktrace$B {" +
|
||||
" static int count1 = 0;" +
|
||||
" static int count2 = 0;" +
|
||||
" public static volatile boolean stop = false;" +
|
||||
" static void localSleep() { " +
|
||||
" try{ " +
|
||||
" Thread.currentThread().sleep(10);" +
|
||||
" } catch(InterruptedException ie) { " +
|
||||
" } " +
|
||||
" } " +
|
||||
" public static void infinite() { " +
|
||||
" System.out.println(\"infinite called\");" +
|
||||
" }" +
|
||||
" public static void throwable() { " +
|
||||
" throw new RuntimeException(\"throwable called\");" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
public static String evenNewerB =
|
||||
"class RedefineRunningMethodsWithBacktrace$B {" +
|
||||
" static int count1 = 0;" +
|
||||
" static int count2 = 0;" +
|
||||
" public static volatile boolean stop = false;" +
|
||||
" static void localSleep() { " +
|
||||
" try{ " +
|
||||
" Thread.currentThread().sleep(1);" +
|
||||
" } catch(InterruptedException ie) { " +
|
||||
" } " +
|
||||
" } " +
|
||||
" public static void infinite() { }" +
|
||||
" public static void throwable() { " +
|
||||
" throw new RuntimeException(\"throwable called\");" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
static class B {
|
||||
static int count1 = 0;
|
||||
static int count2 = 0;
|
||||
public static volatile boolean stop = false;
|
||||
static void localSleep() {
|
||||
try {
|
||||
Thread.currentThread().sleep(10);//sleep for 10 ms
|
||||
} catch(InterruptedException ie) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void infinite() {
|
||||
while (!stop) { count1++; localSleep(); }
|
||||
}
|
||||
public static void throwable() {
|
||||
// add some stuff to the original constant pool
|
||||
String s1 = new String ("string1");
|
||||
String s2 = new String ("string2");
|
||||
String s3 = new String ("string3");
|
||||
String s4 = new String ("string4");
|
||||
String s5 = new String ("string5");
|
||||
String s6 = new String ("string6");
|
||||
String s7 = new String ("string7");
|
||||
String s8 = new String ("string8");
|
||||
String s9 = new String ("string9");
|
||||
String s10 = new String ("string10");
|
||||
String s11 = new String ("string11");
|
||||
String s12 = new String ("string12");
|
||||
String s13 = new String ("string13");
|
||||
String s14 = new String ("string14");
|
||||
String s15 = new String ("string15");
|
||||
String s16 = new String ("string16");
|
||||
String s17 = new String ("string17");
|
||||
String s18 = new String ("string18");
|
||||
String s19 = new String ("string19");
|
||||
throw new RuntimeException("throwable called");
|
||||
}
|
||||
}
|
||||
|
||||
private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
|
||||
System.out.println("touchRedefinedMethodInBacktrace: ");
|
||||
throwable.printStackTrace(); // this actually crashes with the bug in
|
||||
// java_lang_StackTraceElement::create()
|
||||
|
||||
// Make sure that we can convert the backtrace, which is referring to
|
||||
// the redefined method, to a StrackTraceElement[] without crashing.
|
||||
StackTraceElement[] stackTrace = throwable.getStackTrace();
|
||||
for (int i = 0; i < stackTrace.length; i++) {
|
||||
StackTraceElement frame = stackTrace[i];
|
||||
assertNotNull(frame.getClassName(),
|
||||
"\nTest failed: trace[" + i + "].getClassName() returned null");
|
||||
assertNotNull(frame.getMethodName(),
|
||||
"\nTest failed: trace[" + i + "].getMethodName() returned null");
|
||||
}
|
||||
}
|
||||
|
||||
private static Throwable getThrowableInB() {
|
||||
Throwable t = null;
|
||||
try {
|
||||
B.throwable();
|
||||
} catch (Exception e) {
|
||||
t = e;
|
||||
// Don't print here because Throwable will cache the constructed stacktrace
|
||||
// e.printStackTrace();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
new Thread() {
|
||||
public void run() {
|
||||
B.infinite();
|
||||
}
|
||||
}.start();
|
||||
|
||||
Throwable t1 = getThrowableInB();
|
||||
|
||||
RedefineClassHelper.redefineClass(B.class, newB);
|
||||
|
||||
System.gc();
|
||||
|
||||
Throwable t2 = getThrowableInB();
|
||||
|
||||
B.infinite();
|
||||
|
||||
for (int i = 0; i < 20 ; i++) {
|
||||
String s = new String("some garbage");
|
||||
System.gc();
|
||||
}
|
||||
|
||||
RedefineClassHelper.redefineClass(B.class, evenNewerB);
|
||||
System.gc();
|
||||
|
||||
Throwable t3 = getThrowableInB();
|
||||
|
||||
for (int i = 0; i < 20 ; i++) {
|
||||
B.infinite();
|
||||
String s = new String("some garbage");
|
||||
System.gc();
|
||||
}
|
||||
|
||||
touchRedefinedMethodInBacktrace(t1);
|
||||
touchRedefinedMethodInBacktrace(t2);
|
||||
touchRedefinedMethodInBacktrace(t3);
|
||||
|
||||
// purge should clean everything up.
|
||||
B.stop = true;
|
||||
|
||||
for (int i = 0; i < 20 ; i++) {
|
||||
B.infinite();
|
||||
String s = new String("some garbage");
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user