/* * Copyright (c) 2018, 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 8046171 * @summary Test direct and MethodHandle access to private interface methods using invokeinterface semantics * to ensure all receiver typechecks occur as required. * @comment This complements SpecialInterfaceCall which tests invokespecial semantics. * @compile PrivateInterfaceCall.java * @compile PrivateInterfaceCallI4.jasm * @run main/othervm -Xint PrivateInterfaceCall * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 PrivateInterfaceCall * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=2 PrivateInterfaceCall * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=3 PrivateInterfaceCall * @run main/othervm -Xbatch -XX:-TieredCompilation PrivateInterfaceCall
*/
// This is an adaptation of SpecialInterfaceCall to only use private interface methods and with // virtual invocation semantics. Because we don't have the same corner cases as for invokespecial // there's no practical difference between the I3 and I2 cases here. But we do have to ensure the // correct versions of the methods get executed. // In addition we add tests that involve calls from nestmates - which also covers the distinction // between the caller being a class and being an interface.
staticvoid invokeDirect(I2 i) {
i.priv_m(); // generates invokeinterface
} staticvoid invokeInterfaceMH(I2 i) throws Throwable { // emulates behaviour of invokeDirect
mh_I2_priv_m_from_I2.invokeExact(i);
} // special case of invoking an Object method via an interface staticvoid invokeInterfaceObjectMH(I2 i) throws Throwable { // emulates invokeInterface of I2.toString on i, which resolves // to Object.toString
String s = (String) mh_I2_toString_from_I2.invokeExact(i);
} // special case of invoking a final Object method via an interface staticvoid invokeInterfaceObjectFinalMH(I2 i) throws Throwable { // emulates invokeInterface of I1.getClass on i, which resolves // to Object.getClass Class<?> c = (Class<?>) mh_I2_getClass_from_I2.invokeExact(i);
}
// This interface acts like I2 but we define directInvoke* methods // that we will rewrite the bytecode of to use invokeinterface // (see PrivateInterfaceCallI4.jasm). interface I4 extends I1 { staticvoid invokeDirect(I4 i) { // invokeinterface I4.toString() thrownew Error("Class file for I4 is not overwritten");
} staticvoid invokeDirectFinal(I4 i) { // invokeinterface I4.getClass() - final method thrownew Error("Class file for I4 is not overwritten");
}
}
// check invocations from nestmates outside the // inheritance hierarchy - and from a class not interface staticvoid invokeDirect(I2 i) {
i.priv_m(); // generates invokeinterface
} staticvoid invokeInterfaceMH(I2 i) throws Throwable {
mh_I2_priv_m_from_PIC.invokeExact(i);
}
// Classes that don't implement I2/I3 but do have a // priv_m method in their hierarchy staticclass D1 implements I1 { } staticclass E { privatevoid priv_m() { thrownew Error("Should not call this"); }
}
// This MH acts like the invocation in I2.invokeDirect with caller I2 static MethodHandle mh_I2_priv_m_from_I2;
// This MH acts like the invocation in I3.invokeDirect with caller I3 static MethodHandle mh_I2_priv_m_from_I3;
// This MH acts like the invocation in PrivateInterfaceCall.invokeDirect // with caller PrivateInterfaceCall static MethodHandle mh_I2_priv_m_from_PIC;
// This MH acts likes an invokeinterface of I2.toString from I2 static MethodHandle mh_I2_toString_from_I2;
// This MH acts likes an invokeinterface of I2.getClass from I2 static MethodHandle mh_I2_getClass_from_I2;
// This looks odd but at runtime the only constraint is that the // receiver is an I2. In contrast in the invokespecial case the // receiver must be an I3.
shouldNotThrow(() -> I3.invokeInterfaceMH(unsafeCastI3(new C2())));
shouldNotThrow(() -> I3.invokeInterfaceMH(new C3()));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.