8141564: Convert TraceItables and PrintVtables to Unified Logging

The former -XX:+TraceItables and +PrintVtables flags have been converted to UL options -Xlog:itables=trace and vtables=trace

Reviewed-by: acorn, coleenp, dholmes
This commit is contained in:
Rachel Protacio 2016-01-07 13:53:20 -05:00
parent 98193d202b
commit 6dac872d4d
15 changed files with 556 additions and 188 deletions

View File

@ -773,9 +773,11 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
if (cp_cache_entry->is_resolved(bytecode)) return;
if (bytecode == Bytecodes::_invokeinterface) {
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
ResourceMark rm(thread);
tty->print_cr("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), info.resolved_method()->name()->as_C_string());
log_develop_trace(itables)("Resolving: klass: %s to method: %s",
info.resolved_klass()->name()->as_C_string(),
info.resolved_method()->name()->as_C_string());
}
}
#ifdef ASSERT

View File

@ -32,9 +32,11 @@
#include "interpreter/bytecode.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/linkResolver.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "prims/methodHandles.hpp"
@ -728,6 +730,36 @@ methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
return resolved_method;
}
static void trace_method_resolution(const char* prefix,
KlassHandle klass,
KlassHandle resolved_klass,
const methodHandle& method,
bool logitables,
int index = -1) {
#ifndef PRODUCT
ResourceMark rm;
outputStream* st;
if (logitables) {
st = LogHandle(itables)::trace_stream();
} else {
st = LogHandle(vtables)::trace_stream();
}
st->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
prefix,
(klass.is_null() ? "<NULL>" : klass->internal_name()),
(resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
Method::name_and_sig_as_C_string(resolved_klass(),
method->name(),
method->signature()),
method->method_holder()->internal_name());
method->print_linkage_flags(st);
if (index != -1) {
st->print("vtable_index:%d", index);
}
st->cr();
#endif // PRODUCT
}
methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info,
bool nostatics, TRAPS) {
@ -784,10 +816,10 @@ methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info,
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
trace_method_resolution("invokeinterface resolved method: caller-class",
link_info.current_klass(), resolved_klass, resolved_method);
tty->cr();
link_info.current_klass(), resolved_klass,
resolved_method, true);
}
return resolved_method;
@ -1032,10 +1064,9 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
trace_method_resolution("invokespecial resolved method: caller-class:",
current_klass, resolved_klass, resolved_method);
tty->cr();
current_klass, resolved_klass, resolved_method, true);
}
return resolved_method;
@ -1104,10 +1135,9 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result,
sel_method->signature()));
}
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
trace_method_resolution("invokespecial selected method: resolved-class:",
resolved_klass, resolved_klass, sel_method);
tty->cr();
resolved_klass, resolved_klass, sel_method, true);
}
// setup result
@ -1158,10 +1188,9 @@ methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
if (PrintVtables && Verbose) {
if (develop_log_is_enabled(Trace, vtables)) {
trace_method_resolution("invokevirtual resolved method: caller-class:",
current_klass, resolved_klass, resolved_method);
tty->cr();
current_klass, resolved_klass, resolved_method, false);
}
return resolved_method;
@ -1239,10 +1268,10 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
selected_method->signature()));
}
if (PrintVtables && Verbose) {
if (develop_log_is_enabled(Trace, vtables)) {
trace_method_resolution("invokevirtual selected method: receiver-class:",
recv_klass, resolved_klass, selected_method);
tty->print_cr("vtable_index:%d", vtable_index);
recv_klass, resolved_klass, selected_method,
false, vtable_index);
}
// setup result
result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
@ -1338,10 +1367,9 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result,
sel_method->signature()));
}
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
trace_method_resolution("invokeinterface selected method: receiver-class",
recv_klass, resolved_klass, sel_method);
tty->cr();
recv_klass, resolved_klass, sel_method, true);
}
// setup result
if (!resolved_method->has_itable_index()) {
@ -1588,28 +1616,3 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result,
result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
wrap_invokedynamic_exception(CHECK);
}
#ifndef PRODUCT
void LinkResolver::trace_method_resolution(const char* prefix,
KlassHandle klass,
KlassHandle resolved_klass,
const methodHandle& method) {
ResourceMark rm;
tty->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ",
prefix,
(klass.is_null() ? "<NULL>" : klass->internal_name()),
(resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()),
Method::name_and_sig_as_C_string(resolved_klass(),
method->name(),
method->signature()),
method->method_holder()->internal_name()
);
method->access_flags().print_on(tty);
if (method->is_default_method()) {
tty->print("default ");
}
if (method->is_overpass()) {
tty->print("overpass ");
}
}
#endif // PRODUCT

View File

@ -295,9 +295,5 @@ class LinkResolver: AllStatic {
static void resolve_invoke(CallInfo& result, Handle recv,
const constantPoolHandle& pool, int index,
Bytecodes::Code byte, TRAPS);
private:
static void trace_method_resolution(const char* prefix, KlassHandle klass,
KlassHandle resolved_klass,
const methodHandle& method) PRODUCT_RETURN;
};
#endif // SHARE_VM_INTERPRETER_LINKRESOLVER_HPP

View File

@ -52,6 +52,7 @@
LOG_TAG(heap) \
LOG_TAG(humongous) \
LOG_TAG(ihop) \
LOG_TAG(itables) \
LOG_TAG(jni) \
LOG_TAG(liveness) \
LOG_TAG(logging) \
@ -80,7 +81,8 @@
LOG_TAG(tlab) \
LOG_TAG(time) \
LOG_TAG(verify) \
LOG_TAG(vmoperation)
LOG_TAG(vmoperation) \
LOG_TAG(vtables)
#define PREFIX_LOG_TAG(T) (LogTag::_##T)

View File

@ -26,6 +26,7 @@
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc/shared/gcLocker.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
@ -134,12 +135,12 @@ int klassVtable::initialize_from_super(KlassHandle super) {
superVtable->verify(tty, true);
#endif
superVtable->copy_vtable_to(table());
#ifndef PRODUCT
if (PrintVtables && Verbose) {
if (develop_log_is_enabled(Trace, vtables)) {
ResourceMark rm;
tty->print_cr("copy vtable from %s to %s size %d", super->internal_name(), klass()->internal_name(), _length);
log_develop_trace(vtables)("copy vtable from %s to %s size %d",
super->internal_name(), klass()->internal_name(),
_length);
}
#endif
return superVtable->length();
}
}
@ -152,9 +153,9 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) {
KlassHandle super (THREAD, klass()->java_super());
int nofNewEntries = 0;
if (PrintVtables && !klass()->is_array_klass()) {
if (!klass()->is_array_klass()) {
ResourceMark rm(THREAD);
tty->print_cr("Initializing: %s", _klass->name()->as_C_string());
log_develop_debug(vtables)("Initializing: %s", _klass->name()->as_C_string());
}
#ifdef ASSERT
@ -271,24 +272,19 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
#endif
if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) {
#ifndef PRODUCT
if (PrintVtables && Verbose) {
if (develop_log_is_enabled(Trace, vtables)) {
ResourceMark rm(THREAD);
outputStream* logst = LogHandle(vtables)::trace_stream();
char* sig = target_method()->name_and_sig_as_C_string();
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
supersuperklass->internal_name(),
_klass->internal_name(), sig, vtable_index);
super_method->access_flags().print_on(tty);
if (super_method->is_default_method()) {
tty->print("default ");
}
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
if (target_method->is_default_method()) {
tty->print("default ");
}
logst->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
supersuperklass->internal_name(),
_klass->internal_name(), sig, vtable_index);
super_method->print_linkage_flags(logst);
logst->print("overriders flags: ");
target_method->print_linkage_flags(logst);
logst->cr();
}
#endif /*PRODUCT*/
break; // return found superk
}
} else {
@ -303,6 +299,29 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
return superk;
}
static void log_vtables(int i, bool overrides, methodHandle target_method,
KlassHandle target_klass, Method* super_method,
Thread* thread) {
#ifndef PRODUCT
if (develop_log_is_enabled(Trace, vtables)) {
ResourceMark rm(thread);
outputStream* logst = LogHandle(vtables)::trace_stream();
char* sig = target_method()->name_and_sig_as_C_string();
if (overrides) {
logst->print("overriding with %s::%s index %d, original flags: ",
target_klass->internal_name(), sig, i);
} else {
logst->print("NOT overriding with %s::%s index %d, original flags: ",
target_klass->internal_name(), sig, i);
}
super_method->print_linkage_flags(logst);
logst->print("overriders flags: ");
target_method->print_linkage_flags(logst);
logst->cr();
}
#endif
}
// Update child's copy of super vtable for overrides
// OR return true if a new vtable entry is required.
// Only called for InstanceKlass's, i.e. not for arrays
@ -396,6 +415,9 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
// get super_klass for method_holder for the found method
InstanceKlass* super_klass = super_method->method_holder();
// Whether the method is being overridden
bool overrides = false;
// private methods are also never overridden
if (!super_method->is_private() &&
(is_default
@ -446,95 +468,39 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
THROW_MSG_(vmSymbols::java_lang_LinkageError(), buf, false);
}
}
}
put_method_at(target_method(), i);
if (!is_default) {
target_method()->set_vtable_index(i);
} else {
if (def_vtable_indices != NULL) {
def_vtable_indices->at_put(default_index, i);
}
assert(super_method->is_default_method() || super_method->is_overpass()
|| super_method->is_abstract(), "default override error");
}
#ifndef PRODUCT
if (PrintVtables && Verbose) {
ResourceMark rm(THREAD);
char* sig = target_method()->name_and_sig_as_C_string();
tty->print("overriding with %s::%s index %d, original flags: ",
target_klass->internal_name(), sig, i);
super_method->access_flags().print_on(tty);
if (super_method->is_default_method()) {
tty->print("default ");
}
if (super_method->is_overpass()) {
tty->print("overpass");
}
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
if (target_method->is_default_method()) {
tty->print("default ");
}
if (target_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();
}
#endif /*PRODUCT*/
put_method_at(target_method(), i);
overrides = true;
if (!is_default) {
target_method()->set_vtable_index(i);
} else {
if (def_vtable_indices != NULL) {
def_vtable_indices->at_put(default_index, i);
}
assert(super_method->is_default_method() || super_method->is_overpass()
|| super_method->is_abstract(), "default override error");
}
} else {
// allocate_new = true; default. We might override one entry,
// but not override another. Once we override one, not need new
#ifndef PRODUCT
if (PrintVtables && Verbose) {
ResourceMark rm(THREAD);
char* sig = target_method()->name_and_sig_as_C_string();
tty->print("NOT overriding with %s::%s index %d, original flags: ",
target_klass->internal_name(), sig,i);
super_method->access_flags().print_on(tty);
if (super_method->is_default_method()) {
tty->print("default ");
}
if (super_method->is_overpass()) {
tty->print("overpass");
}
tty->print("overriders flags: ");
target_method->access_flags().print_on(tty);
if (target_method->is_default_method()) {
tty->print("default ");
}
if (target_method->is_overpass()) {
tty->print("overpass");
}
tty->cr();
}
#endif /*PRODUCT*/
overrides = false;
}
log_vtables(i, overrides, target_method, target_klass, super_method, THREAD);
}
}
return allocate_new;
}
void klassVtable::put_method_at(Method* m, int index) {
#ifndef PRODUCT
if (PrintVtables && Verbose) {
if (develop_log_is_enabled(Trace, vtables)) {
ResourceMark rm;
outputStream* logst = LogHandle(vtables)::trace_stream();
const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : "<NULL>";
tty->print("adding %s at index %d, flags: ", sig, index);
logst->print("adding %s at index %d, flags: ", sig, index);
if (m != NULL) {
m->access_flags().print_on(tty);
if (m->is_default_method()) {
tty->print("default ");
}
if (m->is_overpass()) {
tty->print("overpass");
}
m->print_linkage_flags(logst);
}
tty->cr();
logst->cr();
}
#endif
table()[index].set(m);
}
@ -852,18 +818,16 @@ int klassVtable::fill_in_mirandas(int initialized) {
get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(),
ik()->default_methods(), ik()->local_interfaces());
for (int i = 0; i < mirandas.length(); i++) {
if (PrintVtables && Verbose) {
if (develop_log_is_enabled(Trace, vtables)) {
Method* meth = mirandas.at(i);
ResourceMark rm(Thread::current());
outputStream* logst = LogHandle(vtables)::trace_stream();
if (meth != NULL) {
char* sig = meth->name_and_sig_as_C_string();
tty->print("fill in mirandas with %s index %d, flags: ",
sig, initialized);
meth->access_flags().print_on(tty);
if (meth->is_default_method()) {
tty->print("default ");
}
tty->cr();
logst->print("fill in mirandas with %s index %d, flags: ",
sig, initialized);
meth->print_linkage_flags(logst);
logst->cr();
}
}
put_method_at(mirandas.at(i), initialized);
@ -1036,8 +1000,8 @@ void klassItable::initialize_itable(bool checkconstraints, TRAPS) {
guarantee(size_offset_table() >= 1, "too small");
int num_interfaces = size_offset_table() - 1;
if (num_interfaces > 0) {
if (TraceItables) tty->print_cr("%3d: Initializing itables for %s", ++initialize_count,
_klass->name()->as_C_string());
log_develop_debug(itables)("%3d: Initializing itables for %s", ++initialize_count,
_klass->name()->as_C_string());
// Iterate through all interfaces
@ -1069,8 +1033,8 @@ inline bool interface_method_needs_itable_index(Method* m) {
int klassItable::assign_itable_indices_for_interface(Klass* klass) {
// an interface does not have an itable, but its methods need to be numbered
if (TraceItables) tty->print_cr("%3d: Initializing itable indices for interface %s", ++initialize_count,
klass->name()->as_C_string());
log_develop_debug(itables)("%3d: Initializing itable indices for interface %s",
++initialize_count, klass->name()->as_C_string());
Array<Method*>* methods = InstanceKlass::cast(klass)->methods();
int nof_methods = methods->length();
int ime_num = 0;
@ -1079,24 +1043,18 @@ int klassItable::assign_itable_indices_for_interface(Klass* klass) {
if (interface_method_needs_itable_index(m)) {
assert(!m->is_final_method(), "no final interface methods");
// If m is already assigned a vtable index, do not disturb it.
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
ResourceMark rm;
const char* sig = (m != NULL) ? m->name_and_sig_as_C_string() : "<NULL>";
outputStream* logst = LogHandle(itables)::trace_stream();
assert(m != NULL, "methods can never be null");
const char* sig = m->name_and_sig_as_C_string();
if (m->has_vtable_index()) {
tty->print("vtable index %d for method: %s, flags: ", m->vtable_index(), sig);
logst->print("vtable index %d for method: %s, flags: ", m->vtable_index(), sig);
} else {
tty->print("itable index %d for method: %s, flags: ", ime_num, sig);
logst->print("itable index %d for method: %s, flags: ", ime_num, sig);
}
if (m != NULL) {
m->access_flags().print_on(tty);
if (m->is_default_method()) {
tty->print("default ");
}
if (m->is_overpass()) {
tty->print("overpass");
}
}
tty->cr();
m->print_linkage_flags(logst);
logst->cr();
}
if (!m->has_vtable_index()) {
assert(m->vtable_index() == Method::pending_itable_index, "set by initialize_vtable");
@ -1200,19 +1158,17 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
int ime_num = m->itable_index();
assert(ime_num < ime_count, "oob");
itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target());
if (TraceItables && Verbose) {
if (develop_log_is_enabled(Trace, itables)) {
ResourceMark rm(THREAD);
if (target() != NULL) {
outputStream* logst = LogHandle(itables)::trace_stream();
char* sig = target()->name_and_sig_as_C_string();
tty->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
interf_h()->internal_name(), ime_num, sig,
target()->method_holder()->internal_name());
tty->print("target_method flags: ");
target()->access_flags().print_on(tty);
if (target()->is_default_method()) {
tty->print("default ");
}
tty->cr();
logst->print("interface: %s, ime_num: %d, target: %s, method_holder: %s ",
interf_h()->internal_name(), ime_num, sig,
target()->method_holder()->internal_name());
logst->print("target_method flags: ");
target()->print_linkage_flags(logst);
logst->cr();
}
}
}

View File

@ -2207,6 +2207,15 @@ void Method::print_on(outputStream* st) const {
}
}
void Method::print_linkage_flags(outputStream* st) {
access_flags().print_on(st);
if (is_default_method()) {
st->print("default ");
}
if (is_overpass()) {
st->print("overpass ");
}
}
#endif //PRODUCT
void Method::print_value_on(outputStream* st) const {

View File

@ -939,6 +939,7 @@ class Method : public Metadata {
void print_on(outputStream* st) const;
#endif
void print_value_on(outputStream* st) const;
void print_linkage_flags(outputStream* st) PRODUCT_RETURN;
const char* internal_name() const { return "{method}"; }

View File

@ -741,9 +741,6 @@ public:
product(bool, ForceTimeHighResolution, false, \
"Using high time resolution (for Win32 only)") \
\
develop(bool, TraceItables, false, \
"Trace initialization and use of itables") \
\
develop(bool, TracePcPatching, false, \
"Trace usage of frame::patch_pc") \
\
@ -2699,9 +2696,6 @@ public:
develop(bool, DebugVtables, false, \
"add debugging code to vtable dispatch") \
\
develop(bool, PrintVtables, false, \
"print vtables when printing klass") \
\
notproduct(bool, PrintVtableStats, false, \
"print vtables stats at end of run") \
\

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
import p2.D;
interface InterfaceA {
public void Method1();
public void Method2();
}
class ClassA implements InterfaceA {
public void Method1() {
System.out.println("ClassA's Method1");
}
public void Method2() {
System.out.println("ClassA's Method2");
}
public void Method3() {
System.out.println("ClassA's Method3");
}
public void Method4() {
System.out.println("ClassA's Method4");
}
}
public class ClassB extends ClassA {
public void Method1() {
System.out.println("ClassB's Method1");
}
public void Method3() {
System.out.println("ClassB's Method3");
}
public static void main(String[] args) throws Exception {
ClassB classBObj = new ClassB();
classBObj.Method1();
classBObj.Method2();
classBObj.Method3();
classBObj.Method4();
ClassA classAObj = new ClassA();
classAObj.Method1();
classAObj.Method2();
classAObj.Method3();
classAObj.Method4();
D classD = new D();
D.loadD();
}
}

View File

@ -0,0 +1,58 @@
/*
* 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 8141564
* @summary itables=trace should have logging from each of the statements
* in the code
* @library /testlibrary
* @ignore 8146435
* @compile ClassB.java
* @modules java.base/sun.misc
* java.management
* @run driver ItablesTest
*/
import jdk.test.lib.*;
public class ItablesTest {
public static void main(String[] args) throws Exception {
if (Platform.isDebugBuild()) {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-Xlog:itables=trace", "ClassB");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain(": Initializing itables for ClassB");
output.shouldContain(": Initializing itable indices for interface ");
output.shouldContain("vtable index ");
output.shouldContain("itable index ");
output.shouldContain("target: ClassB.Method1()V, method_holder: ClassB target_method flags: public");
output.shouldContain("invokeinterface resolved method: caller-class");
output.shouldContain("invokespecial resolved method: caller-class:ClassB");
output.shouldContain("invokespecial selected method: resolved-class:ClassB");
output.shouldContain("invokeinterface selected method: receiver-class");
output.shouldContain("Resolving: klass: ");
output.shouldHaveExitValue(0);
}
}
}

View File

@ -0,0 +1,63 @@
/*
* 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 8141564
* @summary vtables=trace should have logging from each of the statements in the code
* @library /testlibrary
* @compile ClassB.java
* p1/A.java
* p2/B.jcod
* p1/C.java
* p2/D.java
* @modules java.base/sun.misc
* java.management
* @run driver VtablesTest
*/
import jdk.test.lib.*;
public class VtablesTest {
public static void main(String[] args) throws Exception {
if (Platform.isDebugBuild()) {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-Xlog:vtables=trace", "ClassB");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("copy vtable from ClassA to ClassB");
output.shouldContain("Initializing: ClassB");
output.shouldContain("adding ClassB.Method1()V");
output.shouldContain("] overriding with ClassB::ClassB.Method2()V");
output.shouldContain("invokevirtual resolved method: caller-class:ClassB");
output.shouldContain("invokevirtual selected method: receiver-class:ClassB");
output.shouldContain("NOT overriding with p2.D::p2.D.nooverride()V");
output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder("-Xlog:vtables=trace", "p1/C");
output = new OutputAnalyzer(pb.start());
output.shouldContain("transitive overriding superclass ");
output.shouldHaveExitValue(0);
}
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.
*/
package p1;
public class A {
public void test() { System.out.println("In A's test method"); }
void nooverride() {}
}

View File

@ -0,0 +1,34 @@
/*
* 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.
*/
package p1;
import p2.B;
public class C extends B {
public void test() { System.out.println("In C's test method"); }
public static void main(String args[]) {
C c = new C();
c.test();
}
}

View File

@ -0,0 +1,125 @@
/*
* 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.
*/
class p2/B {
0xCAFEBABE;
0; // minor version
52; // version
[28] { // Constant Pool
; // first element is empty
Method #6 #14; // #1 at 0x0A
Field #15 #16; // #2 at 0x0F
String #17; // #3 at 0x14
Method #18 #19; // #4 at 0x17
class #20; // #5 at 0x1C
class #21; // #6 at 0x1F
Utf8 "<init>"; // #7 at 0x22
Utf8 "()V"; // #8 at 0x2B
Utf8 "Code"; // #9 at 0x31
Utf8 "LineNumberTable"; // #10 at 0x38
Utf8 "test"; // #11 at 0x4A
Utf8 "SourceFile"; // #12 at 0x52
Utf8 "B.java"; // #13 at 0x5F
NameAndType #7 #8; // #14 at 0x68
class #22; // #15 at 0x6D
NameAndType #23 #24; // #16 at 0x70
Utf8 "In B's test method"; // #17 at 0x75
class #25; // #18 at 0x8A
NameAndType #26 #27; // #19 at 0x8D
Utf8 "p2/B"; // #20 at 0x92
Utf8 "p1/A"; // #21 at 0x99
Utf8 "java/lang/System"; // #22 at 0xA0
Utf8 "out"; // #23 at 0xB3
Utf8 "Ljava/io/PrintStream;"; // #24 at 0xB9
Utf8 "java/io/PrintStream"; // #25 at 0xD1
Utf8 "println"; // #26 at 0xE7
Utf8 "(Ljava/lang/String;)V"; // #27 at 0xF1
} // Constant Pool
0x0021; // access
#5;// this_cpx
#6;// super_cpx
[0] { // Interfaces
} // Interfaces
[0] { // fields
} // fields
[2] { // methods
{ // Member at 0x0115
0x0001; // access
#7; // name_cpx
#8; // sig_cpx
[1] { // Attributes
Attr(#9, 29) { // Code at 0x011D
1; // max_stack
1; // max_locals
Bytes[5]{
0x2AB70001B1;
};
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#10, 6) { // LineNumberTable at 0x0134
[1] { // LineNumberTable
0 5; // at 0x0140
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
;
{ // Member at 0x0140
0x0000; // access
#11; // name_cpx
#8; // sig_cpx
[1] { // Attributes
Attr(#9, 33) { // Code at 0x0148
2; // max_stack
1; // max_locals
Bytes[9]{
0xB200021203B60004;
0xB1;
};
[0] { // Traps
} // end Traps
[1] { // Attributes
Attr(#10, 6) { // LineNumberTable at 0x0163
[1] { // LineNumberTable
0 6; // at 0x016F
}
} // end LineNumberTable
} // Attributes
} // end Code
} // Attributes
} // Member
} // methods
[1] { // Attributes
Attr(#12, 2) { // SourceFile at 0x0171
#13;
} // end SourceFile
} // Attributes
} // end class p2/B

View File

@ -0,0 +1,29 @@
/*
* 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.
*/
package p2;
public class D extends p1.A {
void nooverride() {}
public static void loadD() {}
}