--- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri May 27 16:39:49 2016 +0000
@@ -704,13 +704,14 @@
InstanceKlass* holder,
Symbol* name,
Symbol* sig,
- Bytecodes::Code bc) {
+ Bytecodes::Code bc,
+ constantTag tag) {
EXCEPTION_CONTEXT;
KlassHandle h_accessor(THREAD, accessor);
KlassHandle h_holder(THREAD, holder);
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
methodHandle dest_method;
- LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
+ LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
switch (bc) {
case Bytecodes::_invokestatic:
dest_method =
@@ -796,7 +797,9 @@
if (holder_is_accessible) { // Our declared holder is loaded.
InstanceKlass* lookup = declared_holder->get_instanceKlass();
- Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
+ constantTag tag = cpool->tag_ref_at(index);
+ assert(accessor->get_instanceKlass() == cpool->pool_holder(), "not the pool holder?");
+ Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc, tag);
if (m != NULL &&
(bc == Bytecodes::_invokestatic
? m->method_holder()->is_not_initialized()
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp Fri May 27 16:39:49 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -156,7 +156,8 @@
InstanceKlass* holder,
Symbol* name,
Symbol* sig,
- Bytecodes::Code bc);
+ Bytecodes::Code bc,
+ constantTag tag);
// Get a ciObject from the object factory. Ensures uniqueness
// of ciObjects.
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Fri May 27 16:39:49 2016 +0000
@@ -789,7 +789,8 @@
Symbol* h_name = name()->get_symbol();
Symbol* h_signature = signature()->get_symbol();
- LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
+ LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass,
+ check_access ? LinkInfo::needs_access_check : LinkInfo::skip_access_check);
methodHandle m;
// Only do exact lookup if receiver klass has been linked. Otherwise,
// the vtable has not been setup, and the LinkResolver will fail.
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri May 27 16:39:49 2016 +0000
@@ -231,6 +231,7 @@
// Get name, signature, and static klass
_name = pool->name_ref_at(index);
_signature = pool->signature_ref_at(index);
+ _tag = pool->tag_ref_at(index);
_current_klass = KlassHandle(THREAD, pool->pool_holder());
// Coming from the constant pool always checks access
@@ -573,7 +574,7 @@
Symbol* method_signature = pool->signature_ref_at(index);
KlassHandle current_klass(THREAD, pool->pool_holder());
LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass);
- return resolve_method(link_info, /*require_methodref*/false, THREAD);
+ return resolve_method(link_info, code, THREAD);
}
LinkInfo link_info(pool, index, CHECK_NULL);
@@ -591,9 +592,9 @@
if (code == Bytecodes::_invokeinterface) {
return resolve_interface_method(link_info, code, THREAD);
} else if (code == Bytecodes::_invokevirtual) {
- return resolve_method(link_info, /*require_methodref*/true, THREAD);
+ return resolve_method(link_info, code, THREAD);
} else if (!resolved_klass->is_interface()) {
- return resolve_method(link_info, /*require_methodref*/false, THREAD);
+ return resolve_method(link_info, code, THREAD);
} else {
return resolve_interface_method(link_info, code, THREAD);
}
@@ -663,13 +664,13 @@
}
methodHandle LinkResolver::resolve_method(const LinkInfo& link_info,
- bool require_methodref, TRAPS) {
+ Bytecodes::Code code, TRAPS) {
Handle nested_exception;
KlassHandle resolved_klass = link_info.resolved_klass();
- // 1. check if methodref required, that resolved_klass is not interfacemethodref
- if (require_methodref && resolved_klass->is_interface()) {
+ // 1. For invokevirtual, cannot call an interface method
+ if (code == Bytecodes::_invokevirtual && resolved_klass->is_interface()) {
ResourceMark rm(THREAD);
char buf[200];
jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected",
@@ -677,11 +678,20 @@
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
- // 2. lookup method in resolved klass and its super klasses
+ // 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref
+ if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) {
+ ResourceMark rm(THREAD);
+ char buf[200];
+ jio_snprintf(buf, sizeof(buf), "Method %s must be Methodref constant", link_info.method_string());
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ }
+
+
+ // 3. lookup method in resolved klass and its super klasses
methodHandle resolved_method = lookup_method_in_klasses(link_info, true, false, CHECK_NULL);
+ // 4. lookup method in all the interfaces implemented by the resolved klass
if (resolved_method.is_null() && !resolved_klass->is_array_klass()) { // not found in the class hierarchy
- // 3. lookup method in all the interfaces implemented by the resolved klass
resolved_method = lookup_method_in_interfaces(link_info, CHECK_NULL);
if (resolved_method.is_null()) {
@@ -694,8 +704,8 @@
}
}
+ // 5. method lookup failed
if (resolved_method.is_null()) {
- // 4. method lookup failed
ResourceMark rm(THREAD);
THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(),
Method::name_and_sig_as_C_string(resolved_klass(),
@@ -704,7 +714,7 @@
nested_exception, NULL);
}
- // 5. access checks, access checking may be turned off when calling from within the VM.
+ // 6. access checks, access checking may be turned off when calling from within the VM.
KlassHandle current_klass = link_info.current_klass();
if (link_info.check_access()) {
assert(current_klass.not_null() , "current_klass should not be null");
@@ -766,6 +776,14 @@
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
+ // check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref
+ if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) {
+ ResourceMark rm(THREAD);
+ char buf[200];
+ jio_snprintf(buf, sizeof(buf), "Method %s must be InterfaceMethodref constant", link_info.method_string());
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ }
+
// lookup method in this interface or its super, java.lang.Object
// JDK8: also look for static methods
methodHandle resolved_method = lookup_method_in_klasses(link_info, false, true, CHECK_NULL);
@@ -956,7 +974,8 @@
resolved_klass->initialize(CHECK);
// Use updated LinkInfo (to reresolve with resolved_klass as method_holder?)
LinkInfo new_info(resolved_klass, link_info.name(), link_info.signature(),
- link_info.current_klass(), link_info.check_access());
+ link_info.current_klass(),
+ link_info.check_access() ? LinkInfo::needs_access_check : LinkInfo::skip_access_check);
resolved_method = linktime_resolve_static_method(new_info, CHECK);
}
@@ -971,7 +990,7 @@
KlassHandle resolved_klass = link_info.resolved_klass();
methodHandle resolved_method;
if (!resolved_klass->is_interface()) {
- resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL);
+ resolved_method = resolve_method(link_info, Bytecodes::_invokestatic, CHECK_NULL);
} else {
resolved_method = resolve_interface_method(link_info, Bytecodes::_invokestatic, CHECK_NULL);
}
@@ -1014,7 +1033,7 @@
methodHandle resolved_method;
if (!resolved_klass->is_interface()) {
- resolved_method = resolve_method(link_info, /*require_methodref*/false, CHECK_NULL);
+ resolved_method = resolve_method(link_info, Bytecodes::_invokespecial, CHECK_NULL);
} else {
resolved_method = resolve_interface_method(link_info, Bytecodes::_invokespecial, CHECK_NULL);
}
@@ -1164,7 +1183,7 @@
methodHandle LinkResolver::linktime_resolve_virtual_method(const LinkInfo& link_info,
TRAPS) {
// normal method resolution
- methodHandle resolved_method = resolve_method(link_info, /*require_methodref*/true, CHECK_NULL);
+ methodHandle resolved_method = resolve_method(link_info, Bytecodes::_invokevirtual, CHECK_NULL);
assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier");
assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier");
@@ -1173,6 +1192,7 @@
KlassHandle resolved_klass = link_info.resolved_klass();
KlassHandle current_klass = link_info.current_klass();
+ // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method
if (resolved_klass->is_interface() && resolved_method->is_private()) {
ResourceMark rm(THREAD);
char buf[200];
@@ -1482,7 +1502,7 @@
KlassHandle defc = attached_method->method_holder();
Symbol* name = attached_method->name();
Symbol* type = attached_method->signature();
- LinkInfo link_info(defc, name, type, KlassHandle(), /*check_access=*/false);
+ LinkInfo link_info(defc, name, type);
switch(byte) {
case Bytecodes::_invokevirtual:
resolve_virtual_call(result, recv, recv->klass(), link_info,
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Fri May 27 16:39:49 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -137,20 +137,35 @@
KlassHandle _resolved_klass; // class that the constant pool entry points to
KlassHandle _current_klass; // class that owns the constant pool
bool _check_access;
+ constantTag _tag;
public:
+ enum AccessCheck {
+ needs_access_check,
+ skip_access_check
+ };
+
LinkInfo(const constantPoolHandle& pool, int index, TRAPS);
+
// Condensed information from other call sites within the vm.
- LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature,
- KlassHandle current_klass, bool check_access = true) :
+ LinkInfo(KlassHandle resolved_klass, Symbol* name, Symbol* signature, KlassHandle current_klass,
+ AccessCheck check_access = needs_access_check,
+ constantTag tag = JVM_CONSTANT_Invalid) :
_resolved_klass(resolved_klass),
_name(name), _signature(signature), _current_klass(current_klass),
- _check_access(check_access) {}
+ _check_access(check_access == needs_access_check), _tag(tag) {}
+
+ // Case where we just find the method and don't check access against the current class
+ LinkInfo(KlassHandle resolved_klass, Symbol*name, Symbol* signature) :
+ _resolved_klass(resolved_klass),
+ _name(name), _signature(signature), _current_klass(NULL),
+ _check_access(false), _tag(JVM_CONSTANT_Invalid) {}
// accessors
Symbol* name() const { return _name; }
Symbol* signature() const { return _signature; }
KlassHandle resolved_klass() const { return _resolved_klass; }
KlassHandle current_klass() const { return _current_klass; }
+ constantTag tag() const { return _tag; }
bool check_access() const { return _check_access; }
char* method_string() const;
@@ -192,7 +207,7 @@
KlassHandle sel_klass, TRAPS);
static methodHandle resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS);
- static methodHandle resolve_method (const LinkInfo& link_info, bool require_methodref, TRAPS);
+ static methodHandle resolve_method (const LinkInfo& link_info, Bytecodes::Code code, TRAPS);
static methodHandle linktime_resolve_static_method (const LinkInfo& link_info, TRAPS);
static methodHandle linktime_resolve_special_method (const LinkInfo& link_info, TRAPS);
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Fri May 27 16:39:49 2016 +0000
@@ -661,8 +661,7 @@
Symbol* h_name = method->name();
Symbol* h_signature = method->signature();
- bool check_access = true;
- LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass, check_access);
+ LinkInfo link_info(h_resolved, h_name, h_signature, caller_klass);
methodHandle m;
// Only do exact lookup if receiver klass has been linked. Otherwise,
// the vtable has not been setup, and the LinkResolver will fail.
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Fri May 27 16:39:49 2016 +0000
@@ -286,11 +286,12 @@
instanceKlassHandle h_holder,
Symbol* name,
Symbol* sig,
- Bytecodes::Code bc) {
+ Bytecodes::Code bc,
+ constantTag tag) {
JVMCI_EXCEPTION_CONTEXT;
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
methodHandle dest_method;
- LinkInfo link_info(h_holder, name, sig, h_accessor, /*check_access*/true);
+ LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
switch (bc) {
case Bytecodes::_invokestatic:
dest_method =
@@ -363,7 +364,8 @@
if (holder_is_accessible) { // Our declared holder is loaded.
instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
- methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc);
+ constantTag tag = cpool->tag_ref_at(index);
+ methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc, tag);
if (!m.is_null() &&
(bc == Bytecodes::_invokestatic
? InstanceKlass::cast(m->method_holder())->is_not_initialized()
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Fri May 27 16:39:49 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -130,7 +130,8 @@
instanceKlassHandle holder,
Symbol* name,
Symbol* sig,
- Bytecodes::Code bc);
+ Bytecodes::Code bc,
+ constantTag tag);
private:
--- a/hotspot/src/share/vm/oops/constantPool.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Fri May 27 16:39:49 2016 +0000
@@ -417,6 +417,19 @@
return extract_high_short_from_int(ref_index);
}
+constantTag ConstantPool::impl_tag_ref_at(int which, bool uncached) {
+ int pool_index = which;
+ if (!uncached && cache() != NULL) {
+ if (ConstantPool::is_invokedynamic_index(which)) {
+ // Invokedynamic index is index into resolved_references
+ pool_index = invokedynamic_cp_cache_entry_at(which)->constant_pool_index();
+ } else {
+ // change byte-ordering and go via cache
+ pool_index = remap_instruction_operand_from_cache(which);
+ }
+ }
+ return tag_at(pool_index);
+}
int ConstantPool::impl_klass_ref_index_at(int which, bool uncached) {
guarantee(!ConstantPool::is_invokedynamic_index(which),
@@ -672,6 +685,7 @@
int callee_index = this_cp->method_handle_klass_index_at(index);
Symbol* name = this_cp->method_handle_name_ref_at(index);
Symbol* signature = this_cp->method_handle_signature_ref_at(index);
+ constantTag m_tag = this_cp->tag_at(this_cp->method_handle_index_at(index));
{ ResourceMark rm(THREAD);
log_debug(class, resolve)("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
ref_kind, index, this_cp->method_handle_index_at(index),
@@ -681,6 +695,15 @@
{ Klass* k = klass_at_impl(this_cp, callee_index, true, CHECK_NULL);
callee = KlassHandle(THREAD, k);
}
+ if ((callee->is_interface() && m_tag.is_method()) ||
+ (!callee->is_interface() && m_tag.is_interface_method())) {
+ ResourceMark rm(THREAD);
+ char buf[200];
+ jio_snprintf(buf, sizeof(buf), "Inconsistent constant data for %s.%s%s at index %d",
+ callee->name()->as_C_string(), name->as_C_string(), signature->as_C_string(), index);
+ THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ }
+
KlassHandle klass(THREAD, this_cp->pool_holder());
Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
callee, name, signature,
--- a/hotspot/src/share/vm/oops/constantPool.hpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Fri May 27 16:39:49 2016 +0000
@@ -643,6 +643,8 @@
int remap_instruction_operand_from_cache(int operand); // operand must be biased by CPCACHE_INDEX_TAG
+ constantTag tag_ref_at(int cp_cache_index) { return impl_tag_ref_at(cp_cache_index, false); }
+
// Lookup for entries consisting of (name_index, signature_index)
int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt)
int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt)
@@ -763,6 +765,7 @@
Symbol* impl_signature_ref_at(int which, bool uncached);
int impl_klass_ref_index_at(int which, bool uncached);
int impl_name_and_type_ref_index_at(int which, bool uncached);
+ constantTag impl_tag_ref_at(int which, bool uncached);
// Used while constructing constant pool (only by ClassFileParser)
jint klass_index_at(int which) {
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Fri May 27 16:39:49 2016 +0000
@@ -713,12 +713,16 @@
TempNewSymbol type = lookup_signature(type_str(), (mh_invoke_id != vmIntrinsics::_none), CHECK_(empty));
if (type == NULL) return empty; // no such signature exists in the VM
+ LinkInfo::AccessCheck access_check = caller.not_null() ?
+ LinkInfo::needs_access_check :
+ LinkInfo::skip_access_check;
+
// Time to do the lookup.
switch (flags & ALL_KINDS) {
case IS_METHOD:
{
CallInfo result;
- LinkInfo link_info(defc, name, type, caller, caller.not_null());
+ LinkInfo link_info(defc, name, type, caller, access_check);
{
assert(!HAS_PENDING_EXCEPTION, "");
if (ref_kind == JVM_REF_invokeStatic) {
@@ -755,7 +759,7 @@
case IS_CONSTRUCTOR:
{
CallInfo result;
- LinkInfo link_info(defc, name, type, caller, caller.not_null());
+ LinkInfo link_info(defc, name, type, caller, access_check);
{
assert(!HAS_PENDING_EXCEPTION, "");
if (name == vmSymbols::object_initializer_name()) {
@@ -776,7 +780,7 @@
fieldDescriptor result; // find_field initializes fd if found
{
assert(!HAS_PENDING_EXCEPTION, "");
- LinkInfo link_info(defc, name, type, caller, /*check_access*/false);
+ LinkInfo link_info(defc, name, type, caller, LinkInfo::skip_access_check);
LinkResolver::resolve_field(result, link_info, Bytecodes::_nop, false, THREAD);
if (HAS_PENDING_EXCEPTION) {
return empty;
--- a/hotspot/src/share/vm/runtime/javaCalls.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/runtime/javaCalls.cpp Fri May 27 16:39:49 2016 +0000
@@ -183,7 +183,7 @@
CallInfo callinfo;
Handle receiver = args->receiver();
KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass());
- LinkInfo link_info(spec_klass, name, signature, KlassHandle(), /*check_access*/false);
+ LinkInfo link_info(spec_klass, name, signature);
LinkResolver::resolve_virtual_call(
callinfo, receiver, recvrKlass, link_info, true, CHECK);
methodHandle method = callinfo.selected_method();
@@ -220,7 +220,7 @@
void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
CallInfo callinfo;
- LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+ LinkInfo link_info(klass, name, signature);
LinkResolver::resolve_special_call(callinfo, link_info, CHECK);
methodHandle method = callinfo.selected_method();
assert(method.not_null(), "should have thrown exception");
@@ -255,7 +255,7 @@
void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
CallInfo callinfo;
- LinkInfo link_info(klass, name, signature, KlassHandle(), /*check_access*/false);
+ LinkInfo link_info(klass, name, signature);
LinkResolver::resolve_static_call(callinfo, link_info, true, CHECK);
methodHandle method = callinfo.selected_method();
assert(method.not_null(), "should have thrown exception");
--- a/hotspot/src/share/vm/runtime/reflection.cpp Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Fri May 27 16:39:49 2016 +0000
@@ -998,7 +998,7 @@
Symbol* signature = method->signature();
Symbol* name = method->name();
LinkResolver::resolve_interface_call(info, receiver, recv_klass,
- LinkInfo(klass, name, signature, KlassHandle(), false),
+ LinkInfo(klass, name, signature),
true,
CHECK_(methodHandle()));
return info.selected_method();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ConstantPool/BadMethodHandles.java Fri May 27 16:39:49 2016 +0000
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2016, 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 8087223
+ * @summary Adding constantTag to keep method call consistent with it.
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.misc
+ * java.management
+ * @compile -XDignore.symbol.file BadMethodHandles.java
+ * @run main/othervm BadMethodHandles
+ */
+
+import jdk.internal.org.objectweb.asm.*;
+import java.io.FileOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+public class BadMethodHandles {
+
+ static byte[] dumpBadInterfaceMethodref() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(52, ACC_PUBLIC | ACC_SUPER, "BadInterfaceMethodref", null, "java/lang/Object", null);
+ Handle handle1 =
+ new Handle(Opcodes.H_INVOKEINTERFACE, "BadInterfaceMethodref", "m", "()V");
+ Handle handle2 =
+ new Handle(Opcodes.H_INVOKEINTERFACE, "BadInterfaceMethodref", "staticM", "()V");
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "m", "()V", null, null);
+ mv.visitCode();
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn("hello from m");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "staticM", "()V", null, null);
+ mv.visitCode();
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn("hello from staticM");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 1);
+ mv.visitEnd();
+ }
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runm", "()V", null, null);
+ mv.visitCode();
+ // REF_invokeStatic
+ mv.visitLdcInsn(handle1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runStaticM", "()V", null, null);
+ mv.visitCode();
+ // REF_invokeStatic
+ mv.visitLdcInsn(handle2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ static byte[] dumpIBad() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(52, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "IBad", null, "java/lang/Object", null);
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "m", "()V", null, null);
+ mv.visitCode();
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn("hello from m");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "staticM", "()V", null, null);
+ mv.visitCode();
+ mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ mv.visitLdcInsn("hello from staticM");
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false/*intf*/);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(3, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ static byte[] dumpBadMethodref() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(52, ACC_PUBLIC | ACC_SUPER, "BadMethodref", null, "java/lang/Object", new String[]{"IBad"});
+ Handle handle1 =
+ new Handle(Opcodes.H_INVOKEINTERFACE, "BadMethodref", "m", "()V");
+ Handle handle2 =
+ new Handle(Opcodes.H_INVOKEINTERFACE, "BadMethodref", "staticM", "()V");
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runm", "()V", null, null);
+ mv.visitCode();
+ // REF_invokeStatic
+ mv.visitLdcInsn(handle1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "runStaticM", "()V", null, null);
+ mv.visitCode();
+ // REF_invokeStatic
+ mv.visitLdcInsn(handle2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invoke", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+ static class CL extends ClassLoader {
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ byte[] classBytes = null;
+ switch (name) {
+ case "BadInterfaceMethodref": classBytes = dumpBadInterfaceMethodref(); break;
+ case "BadMethodref" : classBytes = dumpBadMethodref(); break;
+ case "IBad" : classBytes = dumpIBad(); break;
+ default : throw new ClassNotFoundException(name);
+ }
+ return defineClass(name, classBytes, 0, classBytes.length);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ try (FileOutputStream fos = new FileOutputStream("BadInterfaceMethodref.class")) {
+ fos.write(dumpBadInterfaceMethodref());
+ }
+ try (FileOutputStream fos = new FileOutputStream("IBad.class")) {
+ fos.write(dumpIBad());
+ }
+ try (FileOutputStream fos = new FileOutputStream("BadMethodref.class")) {
+ fos.write(dumpBadMethodref());
+ }
+
+ Class<?> cls = (new CL()).loadClass("BadInterfaceMethodref");
+ String[] methods = {"runm", "runStaticM"};
+ System.out.println("Test BadInterfaceMethodref:");
+ int success = 0;
+ for (String name : methods) {
+ try {
+ System.out.printf("invoke %s: \n", name);
+ cls.getMethod(name).invoke(cls.newInstance());
+ System.out.println("FAILED - ICCE should be thrown");
+ } catch (Throwable e) {
+ if (e instanceof InvocationTargetException && e.getCause() != null &&
+ e.getCause() instanceof IncompatibleClassChangeError) {
+ System.out.println("PASSED - expected ICCE thrown");
+ success++;
+ continue;
+ } else {
+ System.out.println("FAILED with wrong exception" + e);
+ throw e;
+ }
+ }
+ }
+ if (success != methods.length) {
+ throw new Exception("BadInterfaceMethodRef Failed to catch IncompatibleClassChangeError");
+ }
+ System.out.println("Test BadMethodref:");
+ cls = (new CL()).loadClass("BadMethodref");
+ success = 0;
+ for (String name : methods) {
+ try {
+ System.out.printf("invoke %s: \n", name);
+ cls.getMethod(name).invoke(cls.newInstance());
+ System.out.println("FAILED - ICCE should be thrown");
+ } catch (Throwable e) {
+ if (e instanceof InvocationTargetException && e.getCause() != null &&
+ e.getCause() instanceof IncompatibleClassChangeError) {
+ System.out.println("PASSED - expected ICCE thrown");
+ success++;
+ continue;
+ } else {
+ System.out.println("FAILED with wrong exception" + e);
+ throw e;
+ }
+ }
+ }
+ if (success != methods.length) {
+ throw new Exception("BadMethodRef Failed to catch IncompatibleClassChangeError");
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/ConstantPool/IntfMethod.java Fri May 27 16:39:49 2016 +0000
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016, 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 8087223
+ * @summary Adding constantTag to keep method call consistent with it.
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.base/jdk.internal.misc
+ * java.management
+ * @compile -XDignore.symbol.file IntfMethod.java
+ * @run main/othervm IntfMethod
+ * @run main/othervm -Xint IntfMethod
+ * @run main/othervm -Xcomp IntfMethod
+ */
+
+
+import jdk.internal.org.objectweb.asm.*;
+import java.io.FileOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+public class IntfMethod {
+ static byte[] dumpC() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(52, ACC_PUBLIC | ACC_SUPER, "C", null, "java/lang/Object", new String[]{"I"});
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testSpecialIntf", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "I", "f1", "()V", /*itf=*/false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testStaticIntf", "()V", null, null);
+ mv.visitCode();
+ mv.visitMethodInsn(INVOKESTATIC, "I", "f2", "()V", /*itf=*/false);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testSpecialClass", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "C", "f1", "()V", /*itf=*/true);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f2", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "testStaticClass", "()V", null, null);
+ mv.visitCode();
+ mv.visitMethodInsn(INVOKESTATIC, "C", "f2", "()V", /*itf=*/true);
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(1, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ static byte[] dumpI() {
+ ClassWriter cw = new ClassWriter(0);
+ cw.visit(52, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE, "I", null, "java/lang/Object", null);
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "f1", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 1);
+ mv.visitEnd();
+ }
+ {
+ MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f2", "()V", null, null);
+ mv.visitCode();
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(0, 1);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ static class CL extends ClassLoader {
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ byte[] classFile;
+ switch (name) {
+ case "I": classFile = dumpI(); break;
+ case "C": classFile = dumpC(); break;
+ default:
+ throw new ClassNotFoundException(name);
+ }
+ return defineClass(name, classFile, 0, classFile.length);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ Class<?> cls = (new CL()).loadClass("C");
+ try (FileOutputStream fos = new FileOutputStream("I.class")) { fos.write(dumpI()); }
+ try (FileOutputStream fos = new FileOutputStream("C.class")) { fos.write(dumpC()); }
+
+ int success = 0;
+ for (String name : new String[] { "testSpecialIntf", "testStaticIntf", "testSpecialClass", "testStaticClass"}) {
+ System.out.printf("%s: ", name);
+ try {
+ cls.getMethod(name).invoke(cls.newInstance());
+ System.out.println("FAILED - ICCE not thrown");
+ } catch (Throwable e) {
+ if (e instanceof InvocationTargetException &&
+ e.getCause() != null && e.getCause() instanceof IncompatibleClassChangeError) {
+ System.out.println("PASSED - expected ICCE thrown");
+ success++;
+ continue;
+ }
+ }
+ }
+ if (success != 4) throw new Exception("Failed to catch ICCE");
+ }
+}
--- a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Clazz.java Fri May 27 16:39:49 2016 +0000
@@ -72,6 +72,6 @@
public Clazz(String name, String extending, int access, int classFileVersion, int index, String... implementing) {
super(name, extending == null ? "java/lang/Object" : extending, access + ACC_SUPER, classFileVersion, index, implementing);
// Add the default constructor
- addMethod("<init>", "()V", ACC_PUBLIC).makeConstructor(extending);
+ addMethod("<init>", "()V", ACC_PUBLIC).makeConstructor(extending, false);
}
}
--- a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/Method.java Fri May 27 16:39:49 2016 +0000
@@ -59,14 +59,12 @@
private final String ownerClassName;
private final ClassVisitor cv;
private final MethodVisitor mv;
- private final boolean isInterface;
private final ClassBuilder.ExecutionMode execMode;
public Method(ClassConstruct ownerClass, ClassVisitor cv, String name, String descriptor, int access,
ClassBuilder.ExecutionMode execMode) {
this.ownerClassName = ownerClass.getName();
this.ownerClass = ownerClass;
- this.isInterface = ownerClass.isInterface();
this.execMode = execMode;
this.cv = cv;
mv = cv.visitMethod(access, name, descriptor, null, null);
@@ -91,12 +89,12 @@
public void makeSuperCallMethod(int invokeInstruction, String className) {
mv.visitVarInsn(ALOAD, 0);
- makeCall(invokeInstruction, className);
+ makeCall(invokeInstruction, className, false);
mv.visitInsn(POP);
done();
}
- public void defaultInvoke(int instr, String className, String objectRef) {
+ public void defaultInvoke(int instr, String className, String objectRef, boolean isInterface) {
switch (instr) {
case INVOKEVIRTUAL:
defaultInvokeVirtual(className, objectRef);
@@ -105,10 +103,10 @@
defaultInvokeInterface(className, objectRef);
break;
case INVOKESTATIC:
- defaultInvokeStatic(className);
+ defaultInvokeStatic(className, isInterface);
break;
case INVOKESPECIAL:
- defaultInvokeSpecial(className, objectRef);
+ defaultInvokeSpecial(className, objectRef, isInterface);
break;
default:
break;
@@ -118,30 +116,26 @@
mv.visitEnd();
}
- public void defaultInvokeVirtual(String className, String objectRef) {
+ private void defaultInvokeVirtual(String className, String objectRef) {
String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
makeNewObject(objectRef, objectRefPackageName);
makeCall(INVOKEVIRTUAL, className, false);
}
- public void defaultInvokeInterface(String className, String objectRef) {
+ private void defaultInvokeInterface(String className, String objectRef) {
String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
makeNewObject(objectRef, objectRefPackageName);
makeCall(INVOKEINTERFACE, className, true);
}
- public void defaultInvokeSpecial(String className, String objectRef) {
+ private void defaultInvokeSpecial(String className, String objectRef, boolean isInterface) {
String objectRefPackageName = objectRef.substring(0, objectRef.lastIndexOf("/"));
makeNewObject(objectRef, objectRefPackageName);
- makeCall(INVOKESPECIAL, className, false);
+ makeCall(INVOKESPECIAL, className, isInterface);
}
- public void defaultInvokeStatic(String className) {
- makeCall(INVOKESTATIC, className);
- }
-
- private Method makeCall(int invokeInstruction, String className) {
- return makeCall(invokeInstruction, className, isInterface);
+ private void defaultInvokeStatic(String className, boolean isInterface) {
+ makeCall(INVOKESTATIC, className, isInterface);
}
private Method makeCall(int invokeInstruction, String className, boolean isInterface) {
@@ -219,7 +213,7 @@
String className = objectRef.substring(objectRef.lastIndexOf("/") + 1);
makeStaticCall( objectRefPackageName + "/Helper",
"get" + className,
- "()L" + objectRef + ";");
+ "()L" + objectRef + ";", false);
mv.visitVarInsn(ASTORE, 1);
mv.visitVarInsn(ALOAD, 1);
}
@@ -236,12 +230,12 @@
mv.visitEnd();
}
- public Method makeStaticCall(String classname, String method, String descriptor) {
+ public Method makeStaticCall(String classname, String method, String descriptor, boolean isInterface) {
mv.visitMethodInsn(INVOKESTATIC, classname, method, descriptor, isInterface);
return this;
}
- public void makeConstructor(String extending) {
+ public void makeConstructor(String extending, boolean isInterface) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, extending == null ? "java/lang/Object" : extending, "<init>", "()V", isInterface);
mv.visitInsn(RETURN);
--- a/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java Fri May 27 14:49:05 2016 +0000
+++ b/hotspot/test/runtime/SelectionResolution/classes/selectionresolution/TestBuilder.java Fri May 27 16:39:49 2016 +0000
@@ -53,9 +53,10 @@
Method m = clazz.addMethod("test", "()Ljava/lang/Integer;", ACC_PUBLIC + ACC_STATIC, execMode);
m.defaultInvoke(getInvokeInstruction(testcase.invoke),
getName(testcase.methodref),
- getName(testcase.objectref));
+ getName(testcase.objectref),
+ testcase.hier.isInterface(testcase.methodref));
- mainMethod.makeStaticCall(clazz.getName(), "test", "()Ljava/lang/Integer;").done();
+ mainMethod.makeStaticCall(clazz.getName(), "test", "()Ljava/lang/Integer;", false).done();
}
private static int getInvokeInstruction(SelectionResolutionTestCase.InvokeInstruction instr) {