# HG changeset patch # User jbachorik # Date 1398775022 -7200 # Node ID 5d05d4c0de7f9c6e9a8e4d3a10a225d186c5b601 # Parent dda4c98ed5e984b203e976b0dd9aa2a735fc78d2 8042096: Backout JDK-8042091 Reviewed-by: sla diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/make/data/jdwp/jdwp.spec --- a/jdk/make/data/jdwp/jdwp.spec Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/make/data/jdwp/jdwp.spec Tue Apr 29 14:37:02 2014 +0200 @@ -1147,8 +1147,7 @@ (ErrorSet (Error INVALID_CLASS "clazz is not the ID of a class.") (Error INVALID_OBJECT "clazz is not a known ID.") - (Error INVALID_METHODID "methodID is not the ID of a static method in " - "this class type or one of its superclasses.") + (Error INVALID_METHODID "methodID is not the ID of a method.") (Error INVALID_THREAD) (Error THREAD_NOT_SUSPENDED) (Error VM_DEAD) @@ -1251,83 +1250,6 @@ ) ) (CommandSet InterfaceType=5 - (Command InvokeMethod=1 - "Invokes a static method. " - "The method must not be a static initializer. " - "The method must be a member of the interface type. " - "

Since JDWP version 1.8 " - "

" - "The method invocation will occur in the specified thread. " - "Method invocation can occur only if the specified thread " - "has been suspended by an event. " - "Method invocation is not supported " - "when the target VM has been suspended by the front-end. " - "

" - "The specified method is invoked with the arguments in the specified " - "argument list. " - "The method invocation is synchronous; the reply packet is not " - "sent until the invoked method returns in the target VM. " - "The return value (possibly the void value) is " - "included in the reply packet. " - "If the invoked method throws an exception, the " - "exception object ID is set in the reply packet; otherwise, the " - "exception object ID is null. " - "

" - "For primitive arguments, the argument value's type must match the " - "argument's type exactly. For object arguments, there must exist a " - "widening reference conversion from the argument value's type to the " - "argument's type and the argument's type must be loaded. " - "

" - "By default, all threads in the target VM are resumed while " - "the method is being invoked if they were previously " - "suspended by an event or by a command. " - "This is done to prevent the deadlocks " - "that will occur if any of the threads own monitors " - "that will be needed by the invoked method. It is possible that " - "breakpoints or other events might occur during the invocation. " - "Note, however, that this implicit resume acts exactly like " - "the ThreadReference resume command, so if the thread's suspend " - "count is greater than 1, it will remain in a suspended state " - "during the invocation. By default, when the invocation completes, " - "all threads in the target VM are suspended, regardless their state " - "before the invocation. " - "

" - "The resumption of other threads during the invoke can be prevented " - "by specifying the INVOKE_SINGLE_THREADED " - "bit flag in the options field; however, " - "there is no protection against or recovery from the deadlocks " - "described above, so this option should be used with great caution. " - "Only the specified thread will be resumed (as described for all " - "threads above). Upon completion of a single threaded invoke, the invoking thread " - "will be suspended once again. Note that any threads started during " - "the single threaded invocation will not be suspended when the " - "invocation completes. " - "

" - "If the target VM is disconnected during the invoke (for example, through " - "the VirtualMachine dispose command) the method invocation continues. " - (Out - (interfaceType clazz "The interface type ID.") - (threadObject thread "The thread in which to invoke.") - (method methodID "The method to invoke.") - (Repeat arguments - (value arg "The argument value.") - ) - (int options "Invocation options") - ) - (Reply - (value returnValue "The returned value.") - (tagged-object exception "The thrown exception.") - ) - (ErrorSet - (Error INVALID_CLASS "clazz is not the ID of an interface.") - (Error INVALID_OBJECT "clazz is not a known ID.") - (Error INVALID_METHODID "methodID is not the ID of a static method in this " - "interface type or is the ID of a static initializer.") - (Error INVALID_THREAD) - (Error THREAD_NOT_SUSPENDED) - (Error VM_DEAD) - ) - ) ) (CommandSet Method=6 (Command LineTable=1 @@ -1621,7 +1543,7 @@ "

" "By default, all threads in the target VM are resumed while " "the method is being invoked if they were previously " - "suspended by an event or by a command. " + "suspended by an event or by command. " "This is done to prevent the deadlocks " "that will occur if any of the threads own monitors " "that will be needed by the invoked method. It is possible that " @@ -1664,9 +1586,7 @@ (Error INVALID_OBJECT) (Error INVALID_CLASS "clazz is not the ID of a reference " "type.") - (Error INVALID_METHODID "methodID is not the ID of an instance method " - "in this object's type or one of its superclasses, " - "superinterfaces, or implemented interfaces.") + (Error INVALID_METHODID "methodID is not the ID of a method.") (Error INVALID_THREAD) (Error THREAD_NOT_SUSPENDED) (Error VM_DEAD) diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/back/InterfaceTypeImpl.c --- a/jdk/src/share/back/InterfaceTypeImpl.c Tue Apr 29 13:23:08 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1998, 2005, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#include "util.h" -#include "InterfaceTypeImpl.h" -#include "inStream.h" -#include "outStream.h" - -static jboolean -invokeStatic(PacketInputStream *in, PacketOutputStream *out) -{ - return sharedInvoke(in, out); -} - -void *InterfaceType_Cmds[] = { (void *)0x1 - , (void *)invokeStatic -}; diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/back/InterfaceTypeImpl.h --- a/jdk/src/share/back/InterfaceTypeImpl.h Tue Apr 29 13:23:08 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/* - * Copyright (c) 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -extern void *InterfaceType_Cmds[]; diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/back/VirtualMachineImpl.c --- a/jdk/src/share/back/VirtualMachineImpl.c Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/back/VirtualMachineImpl.c Tue Apr 29 14:37:02 2014 +0200 @@ -36,7 +36,7 @@ static char *versionName = "Java Debug Wire Protocol (Reference Implementation)"; static int majorVersion = 1; /* JDWP major version */ -static int minorVersion = 8; /* JDWP minor version */ +static int minorVersion = 6; /* JDWP minor version */ static jboolean version(PacketInputStream *in, PacketOutputStream *out) diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/back/debugDispatch.c --- a/jdk/src/share/back/debugDispatch.c Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/back/debugDispatch.c Tue Apr 29 14:37:02 2014 +0200 @@ -29,7 +29,6 @@ #include "VirtualMachineImpl.h" #include "ReferenceTypeImpl.h" #include "ClassTypeImpl.h" -#include "InterfaceTypeImpl.h" #include "ArrayTypeImpl.h" #include "FieldImpl.h" #include "MethodImpl.h" @@ -68,7 +67,6 @@ l1Array[JDWP_COMMAND_SET(VirtualMachine)] = (void *)VirtualMachine_Cmds; l1Array[JDWP_COMMAND_SET(ReferenceType)] = (void *)ReferenceType_Cmds; l1Array[JDWP_COMMAND_SET(ClassType)] = (void *)ClassType_Cmds; - l1Array[JDWP_COMMAND_SET(InterfaceType)] = (void *)InterfaceType_Cmds; l1Array[JDWP_COMMAND_SET(ArrayType)] = (void *)ArrayType_Cmds; l1Array[JDWP_COMMAND_SET(Field)] = (void *)Field_Cmds; diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/back/util.c --- a/jdk/src/share/back/util.c Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/back/util.c Tue Apr 29 14:37:02 2014 +0200 @@ -591,8 +591,6 @@ invokeType = INVOKE_CONSTRUCTOR; } else if (inStream_command(in) == JDWP_COMMAND(ClassType, InvokeMethod)) { invokeType = INVOKE_STATIC; - } else if (inStream_command(in) == JDWP_COMMAND(InterfaceType, InvokeMethod)) { - invokeType = INVOKE_STATIC; } else if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) { invokeType = INVOKE_INSTANCE; } else { diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/jdi/ClassType.java --- a/jdk/src/share/classes/com/sun/jdi/ClassType.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/jdi/ClassType.java Tue Apr 29 14:37:02 2014 +0200 @@ -103,7 +103,7 @@ *

* Object values must be assignment compatible with the field type * (This implies that the field type must be loaded through the - * enclosing class' class loader). Primitive values must be + * enclosing class's class loader). Primitive values must be * either assignment compatible with the field type or must be * convertible to the field type without loss of information. * See JLS section 5.2 for more information on assignment @@ -153,7 +153,7 @@ *

* Object arguments must be assignment compatible with the argument type * (This implies that the argument type must be loaded through the - * enclosing class' class loader). Primitive arguments must be + * enclosing class's class loader). Primitive arguments must be * either assignment compatible with the argument type or must be * convertible to the argument type without loss of information. * If the method being called accepts a variable number of arguments, @@ -216,7 +216,7 @@ * @return a {@link Value} mirror of the invoked method's return value. * @throws java.lang.IllegalArgumentException if the method is not * a member of this class or a superclass, if the size of the argument list - * does not match the number of declared arguments for the method, or + * does not match the number of declared arguemnts for the method, or * if the method is an initializer, constructor or static intializer. * @throws {@link InvalidTypeException} if any argument in the * argument list is not assignable to the corresponding method argument @@ -230,7 +230,7 @@ * @throws InvalidTypeException If the arguments do not meet this requirement -- * Object arguments must be assignment compatible with the argument * type. This implies that the argument type must be - * loaded through the enclosing class' class loader. + * loaded through the enclosing class's class loader. * Primitive arguments must be either assignment compatible with the * argument type or must be convertible to the argument type without loss * of information. See JLS section 5.2 for more information on assignment @@ -267,7 +267,7 @@ *

* Object arguments must be assignment compatible with the argument type * (This implies that the argument type must be loaded through the - * enclosing class' class loader). Primitive arguments must be + * enclosing class's class loader). Primitive arguments must be * either assignment compatible with the argument type or must be * convertible to the argument type without loss of information. * If the method being called accepts a variable number of arguments, @@ -335,7 +335,7 @@ * @throws InvalidTypeException If the arguments do not meet this requirement -- * Object arguments must be assignment compatible with the argument * type. This implies that the argument type must be - * loaded through the enclosing class' class loader. + * loaded through the enclosing class's class loader. * Primitive arguments must be either assignment compatible with the * argument type or must be convertible to the argument type without loss * of information. See JLS section 5.2 for more information on assignment diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/jdi/InterfaceType.java --- a/jdk/src/share/classes/com/sun/jdi/InterfaceType.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/jdi/InterfaceType.java Tue Apr 29 14:37:02 2014 +0200 @@ -79,121 +79,4 @@ * If none exist, returns a zero length List. */ List implementors(); - - /** - * Invokes the specified static {@link Method} in the - * target VM. The - * specified method must be defined in this interface. - * The method must be a static method - * but not a static initializer. - *

- * The method invocation will occur in the specified thread. - * Method invocation can occur only if the specified thread - * has been suspended by an event which occurred in that thread. - * Method invocation is not supported - * when the target VM has been suspended through - * {@link VirtualMachine#suspend} or when the specified thread - * is suspended through {@link ThreadReference#suspend}. - *

- * The specified method is invoked with the arguments in the specified - * argument list. The method invocation is synchronous; this method - * does not return until the invoked method returns in the target VM. - * If the invoked method throws an exception, this method will throw - * an {@link InvocationException} which contains a mirror to the exception - * object thrown. - *

- * Object arguments must be assignment compatible with the argument type - * (This implies that the argument type must be loaded through the - * enclosing class' class loader). Primitive arguments must be - * either assignment compatible with the argument type or must be - * convertible to the argument type without loss of information. - * If the method being called accepts a variable number of arguments, - * then the last argument type is an array of some component type. - * The argument in the matching position can be omitted, or can be null, - * an array of the same component type, or an argument of the - * component type followed by any number of other arguments of the same - * type. If the argument is omitted, then a 0 length array of the - * component type is passed. The component type can be a primitive type. - * Autoboxing is not supported. - * - * See Section 5.2 of - * The Java™ Language Specification - * for more information on assignment compatibility. - *

- * By default, all threads in the target VM are resumed while - * the method is being invoked if they were previously - * suspended by an event or by {@link VirtualMachine#suspend} or - * {@link ThreadReference#suspend}. This is done to prevent the deadlocks - * that will occur if any of the threads own monitors - * that will be needed by the invoked method. - * Note, however, that this implicit resume acts exactly like - * {@link ThreadReference#resume}, so if the thread's suspend - * count is greater than 1, it will remain in a suspended state - * during the invocation and thus a deadlock could still occur. - * By default, when the invocation completes, - * all threads in the target VM are suspended, regardless their state - * before the invocation. - * It is possible that - * breakpoints or other events might occur during the invocation. - * This can cause deadlocks as described above. It can also cause a deadlock - * if invokeMethod is called from the client's event handler thread. In this - * case, this thread will be waiting for the invokeMethod to complete and - * won't read the EventSet that comes in for the new event. If this - * new EventSet is SUSPEND_ALL, then a deadlock will occur because no - * one will resume the EventSet. To avoid this, all EventRequests should - * be disabled before doing the invokeMethod, or the invokeMethod should - * not be done from the client's event handler thread. - *

- * The resumption of other threads during the invocation can be prevented - * by specifying the {@link #INVOKE_SINGLE_THREADED} - * bit flag in the options argument; however, - * there is no protection against or recovery from the deadlocks - * described above, so this option should be used with great caution. - * Only the specified thread will be resumed (as described for all - * threads above). Upon completion of a single threaded invoke, the invoking thread - * will be suspended once again. Note that any threads started during - * the single threaded invocation will not be suspended when the - * invocation completes. - *

- * If the target VM is disconnected during the invoke (for example, through - * {@link VirtualMachine#dispose}) the method invocation continues. - * - * @param thread the thread in which to invoke. - * @param method the {@link Method} to invoke. - * @param arguments the list of {@link Value} arguments bound to the - * invoked method. Values from the list are assigned to arguments - * in the order they appear in the method signature. - * @param options the integer bit flag options. - * @return a {@link Value} mirror of the invoked method's return value. - * @throws java.lang.IllegalArgumentException if the method is not - * a member of this interface, if the size of the argument list - * does not match the number of declared arguments for the method, or - * if the method is not static or is a static initializer. - * @throws {@link InvalidTypeException} if any argument in the - * argument list is not assignable to the corresponding method argument - * type. - * @throws ClassNotLoadedException if any argument type has not yet been loaded - * through the appropriate class loader. - * @throws IncompatibleThreadStateException if the specified thread has not - * been suspended by an event. - * @throws InvocationException if the method invocation resulted in - * an exception in the target VM. - * @throws InvalidTypeException If the arguments do not meet this requirement -- - * Object arguments must be assignment compatible with the argument - * type. This implies that the argument type must be - * loaded through the enclosing class' class loader. - * Primitive arguments must be either assignment compatible with the - * argument type or must be convertible to the argument type without loss - * of information. See JLS section 5.2 for more information on assignment - * compatibility. - * @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}. - * - * @since 1.8 - */ - Value invokeMethod(ThreadReference thread, Method method, - List arguments, int options) - throws InvalidTypeException, - ClassNotLoadedException, - IncompatibleThreadStateException, - InvocationException; } diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/jdi/Method.java --- a/jdk/src/share/classes/com/sun/jdi/Method.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/jdi/Method.java Tue Apr 29 14:37:02 2014 +0200 @@ -138,16 +138,6 @@ boolean isAbstract(); /** - * Determine if this method is a default method - * - * @return true if the method is declared default; - * false otherwise - * - * @since 1.8 - */ - boolean isDefault(); - - /** * Determine if this method is synchronized. * * @return true if the method is declared synchronized; diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/jdi/ObjectReference.java --- a/jdk/src/share/classes/com/sun/jdi/ObjectReference.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/jdi/ObjectReference.java Tue Apr 29 14:37:02 2014 +0200 @@ -194,10 +194,10 @@ * {@link #INVOKE_NONVIRTUAL} bit flag in the options * argument. If this flag is set, the specified method is invoked * whether or not it is overridden for this object's runtime type. - * The method, in this case, must have an implementation, either in a class - * or an interface. This option is useful for performing method invocations - * like those done with the super keyword in the Java programming - * language. + * The method, in this case, must not belong to an interface and + * must not be abstract. This option is useful for performing method + * invocations like those done with the super keyword in + * the Java programming language. *

* By default, all threads in the target VM are resumed while * the method is being invoked if they were previously @@ -246,10 +246,10 @@ * @return a {@link Value} mirror of the invoked method's return value. * @throws java.lang.IllegalArgumentException if the method is not * a member of this object's class, if the size of the argument list - * does not match the number of declared arguments for the method, + * does not match the number of declared arguemnts for the method, * if the method is a constructor or static intializer, or * if {@link #INVOKE_NONVIRTUAL} is specified and the method is - * either abstract or a non-default interface member. + * either abstract or an interface member. * @throws {@link InvalidTypeException} if any argument in the * argument list is not assignable to the corresponding method argument * type. diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java --- a/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/tools/example/debug/expr/LValue.java Tue Apr 29 14:37:02 2014 +0200 @@ -559,9 +559,6 @@ } else if (refType instanceof ClassType) { ClassType clazz = (ClassType)refType; return jdiValue = clazz.invokeMethod(thread, matchingMethod, methodArguments, 0); - } else if (refType instanceof InterfaceType) { - InterfaceType iface = (InterfaceType)refType; - return jdiValue = iface.invokeMethod(thread, matchingMethod, methodArguments, 0); } else { throw new InvalidTypeException("Cannot invoke static method on " + refType.name()); diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java Tue Apr 29 14:37:02 2014 +0200 @@ -29,27 +29,9 @@ import java.util.*; -final public class ClassTypeImpl extends InvokableTypeImpl +public class ClassTypeImpl extends ReferenceTypeImpl implements ClassType { - private static class IResult implements InvocationResult { - final private JDWP.ClassType.InvokeMethod rslt; - - public IResult(JDWP.ClassType.InvokeMethod rslt) { - this.rslt = rslt; - } - - @Override - public ObjectReferenceImpl getException() { - return rslt.exception; - } - - @Override - public ValueImpl getResult() { - return rslt.returnValue; - } - } - private boolean cachedSuperclass = false; private ClassType superclass = null; private int lastLine = -1; @@ -83,7 +65,6 @@ return superclass; } - @Override public List interfaces() { if (interfaces == null) { interfaces = getInterfaces(); @@ -91,9 +72,26 @@ return interfaces; } - @Override - public List allInterfaces() { - return getAllInterfaces(); + void addInterfaces(List list) { + List immediate = interfaces(); + list.addAll(interfaces()); + + Iterator iter = immediate.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); + interfaze.addSuperinterfaces(list); + } + + ClassTypeImpl superclass = (ClassTypeImpl)superclass(); + if (superclass != null) { + superclass.addInterfaces(list); + } + } + + public List allInterfaces() { + List all = new ArrayList(); + addInterfaces(all); + return all; } public List subclasses() { @@ -161,6 +159,28 @@ } } + PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, + final MethodImpl method, + final ValueImpl[] args, + final int options) { + CommandSender sender = + new CommandSender() { + public PacketStream send() { + return JDWP.ClassType.InvokeMethod.enqueueCommand( + vm, ClassTypeImpl.this, thread, + method.ref(), args, options); + } + }; + + PacketStream stream; + if ((options & INVOKE_SINGLE_THREADED) != 0) { + stream = thread.sendResumingCommand(sender); + } else { + stream = vm.sendResumingCommand(sender); + } + return stream; + } + PacketStream sendNewInstanceCommand(final ThreadReferenceImpl thread, final MethodImpl method, final ValueImpl[] args, @@ -183,6 +203,52 @@ return stream; } + public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, + List origArguments, int options) + throws InvalidTypeException, + ClassNotLoadedException, + IncompatibleThreadStateException, + InvocationException { + validateMirror(threadIntf); + validateMirror(methodIntf); + validateMirrorsOrNulls(origArguments); + + MethodImpl method = (MethodImpl)methodIntf; + ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; + + validateMethodInvocation(method); + + List arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); + + ValueImpl[] args = arguments.toArray(new ValueImpl[0]); + JDWP.ClassType.InvokeMethod ret; + try { + PacketStream stream = + sendInvokeCommand(thread, method, args, options); + ret = JDWP.ClassType.InvokeMethod.waitForReply(vm, stream); + } catch (JDWPException exc) { + if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { + throw new IncompatibleThreadStateException(); + } else { + throw exc.toJDIException(); + } + } + + /* + * There is an implict VM-wide suspend at the conclusion + * of a normal (non-single-threaded) method invoke + */ + if ((options & INVOKE_SINGLE_THREADED) == 0) { + vm.notifySuspend(); + } + + if (ret.exception != null) { + throw new InvocationException(ret.exception); + } else { + return ret.returnValue; + } + } + public ObjectReference newInstance(ThreadReference threadIntf, Method methodIntf, List origArguments, @@ -245,6 +311,58 @@ return method; } + public List allMethods() { + ArrayList list = new ArrayList(methods()); + + ClassType clazz = superclass(); + while (clazz != null) { + list.addAll(clazz.methods()); + clazz = clazz.superclass(); + } + + /* + * Avoid duplicate checking on each method by iterating through + * duplicate-free allInterfaces() rather than recursing + */ + for (InterfaceType interfaze : allInterfaces()) { + list.addAll(interfaze.methods()); + } + + return list; + } + + List inheritedTypes() { + List inherited = new ArrayList(); + if (superclass() != null) { + inherited.add(0, (ReferenceType)superclass()); /* insert at front */ + } + for (ReferenceType rt : interfaces()) { + inherited.add(rt); + } + return inherited; + } + + void validateMethodInvocation(Method method) + throws InvalidTypeException, + InvocationException { + /* + * Method must be in this class or a superclass. + */ + ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType(); + if (!declType.isAssignableFrom(this)) { + throw new IllegalArgumentException("Invalid method"); + } + + /* + * Method must be a static and not a static initializer + */ + if (!method.isStatic()) { + throw new IllegalArgumentException("Cannot invoke instance method on a class type"); + } else if (method.isStaticInitializer()) { + throw new IllegalArgumentException("Cannot invoke static initializer"); + } + } + void validateConstructorInvocation(Method method) throws InvalidTypeException, InvocationException { @@ -264,33 +382,51 @@ } } + @Override + void addVisibleMethods(Map methodMap, Set seenInterfaces) { + /* + * Add methods from + * parent types first, so that the methods in this class will + * overwrite them in the hash table + */ + + Iterator iter = interfaces().iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); + if (!seenInterfaces.contains(interfaze)) { + interfaze.addVisibleMethods(methodMap, seenInterfaces); + seenInterfaces.add(interfaze); + } + } + + ClassTypeImpl clazz = (ClassTypeImpl)superclass(); + if (clazz != null) { + clazz.addVisibleMethods(methodMap, seenInterfaces); + } + + addToMethodMap(methodMap, methods()); + } + + boolean isAssignableTo(ReferenceType type) { + ClassTypeImpl superclazz = (ClassTypeImpl)superclass(); + if (this.equals(type)) { + return true; + } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { + return true; + } else { + List interfaces = interfaces(); + Iterator iter = interfaces.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); + if (interfaze.isAssignableTo(type)) { + return true; + } + } + return false; + } + } public String toString() { return "class " + name() + " (" + loaderString() + ")"; } - - @Override - CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, - MethodImpl method, - ValueImpl[] args, - int options) { - return () -> - JDWP.ClassType.InvokeMethod.enqueueCommand(vm, - ClassTypeImpl.this, - thread, - method.ref(), - args, - options); - } - - @Override - InvocationResult waitForReply(PacketStream stream) throws JDWPException { - return new IResult(JDWP.ClassType.InvokeMethod.waitForReply(vm, stream)); - } - - @Override - boolean canInvoke(Method method) { - // Method must be in this class or a superclass. - return ((ReferenceTypeImpl)method.declaringType()).isAssignableFrom(this); - } } diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java Tue Apr 29 14:37:02 2014 +0200 @@ -29,31 +29,14 @@ import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.Iterator; import java.util.Collections; import java.util.Set; import java.lang.ref.SoftReference; -final public class InterfaceTypeImpl extends InvokableTypeImpl - implements InterfaceType { - - private static class IResult implements InvocationResult { - final private JDWP.InterfaceType.InvokeMethod rslt; - - public IResult(JDWP.InterfaceType.InvokeMethod rslt) { - this.rslt = rslt; - } - - @Override - public ObjectReferenceImpl getException() { - return rslt.exception; - } - - @Override - public ValueImpl getResult() { - return rslt.returnValue; - } - - } +public class InterfaceTypeImpl extends ReferenceTypeImpl + implements InterfaceType { private SoftReference> superinterfacesRef = null; @@ -98,6 +81,102 @@ return implementors; } + @Override + void addVisibleMethods(Map methodMap, Set seenInterfaces) { + /* + * Add methods from + * parent types first, so that the methods in this class will + * overwrite them in the hash table + */ + + for (InterfaceType interfaze : superinterfaces()) { + if (!seenInterfaces.contains(interfaze)) { + ((InterfaceTypeImpl)interfaze).addVisibleMethods(methodMap, seenInterfaces); + seenInterfaces.add(interfaze); + } + } + + addToMethodMap(methodMap, methods()); + } + + public List allMethods() { + ArrayList list = new ArrayList(methods()); + + /* + * It's more efficient if don't do this + * recursively. + */ + for (InterfaceType interfaze : allSuperinterfaces()) { + list.addAll(interfaze.methods()); + } + + return list; + } + + List allSuperinterfaces() { + ArrayList list = new ArrayList(); + addSuperinterfaces(list); + return list; + } + + void addSuperinterfaces(List list) { + /* + * This code is a little strange because it + * builds the list with a more suitable order than the + * depth-first approach a normal recursive solution would + * take. Instead, all direct superinterfaces precede all + * indirect ones. + */ + + /* + * Get a list of direct superinterfaces that's not already in the + * list being built. + */ + List immediate = new ArrayList(superinterfaces()); + Iterator iter = immediate.iterator(); + while (iter.hasNext()) { + InterfaceType interfaze = iter.next(); + if (list.contains(interfaze)) { + iter.remove(); + } + } + + /* + * Add all new direct superinterfaces + */ + list.addAll(immediate); + + /* + * Recurse for all new direct superinterfaces. + */ + iter = immediate.iterator(); + while (iter.hasNext()) { + InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next(); + interfaze.addSuperinterfaces(list); + } + } + + boolean isAssignableTo(ReferenceType type) { + + // Exact match? + if (this.equals(type)) { + return true; + } else { + // Try superinterfaces. + for (InterfaceType interfaze : superinterfaces()) { + if (((InterfaceTypeImpl)interfaze).isAssignableTo(type)) { + return true; + } + } + + return false; + } + } + + List inheritedTypes() { + return superinterfaces(); + } + public boolean isInitialized() { return isPrepared(); } @@ -105,39 +184,4 @@ public String toString() { return "interface " + name() + " (" + loaderString() + ")"; } - - @Override - InvocationResult waitForReply(PacketStream stream) throws JDWPException { - return new IResult(JDWP.InterfaceType.InvokeMethod.waitForReply(vm, stream)); - } - - @Override - CommandSender getInvokeMethodSender(final ThreadReferenceImpl thread, - final MethodImpl method, - final ValueImpl[] args, - final int options) { - return () -> - JDWP.InterfaceType.InvokeMethod.enqueueCommand(vm, - InterfaceTypeImpl.this, - thread, - method.ref(), - args, - options); - } - - @Override - ClassType superclass() { - return null; - } - - @Override - List interfaces() { - return superinterfaces(); - } - - @Override - boolean canInvoke(Method method) { - // method must be directly in this interface - return this.equals(method.declaringType()); - } -} \ No newline at end of file +} diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java Tue Apr 29 13:23:08 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2014, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.tools.jdi; - -import com.sun.jdi.ClassNotLoadedException; -import com.sun.jdi.ClassType; -import com.sun.jdi.IncompatibleThreadStateException; -import com.sun.jdi.InterfaceType; -import com.sun.jdi.InvalidTypeException; -import com.sun.jdi.InvocationException; -import com.sun.jdi.Method; -import com.sun.jdi.ReferenceType; -import com.sun.jdi.ThreadReference; -import com.sun.jdi.Value; -import com.sun.jdi.VirtualMachine; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * A supertype for ReferenceTypes allowing method invocations - */ -abstract class InvokableTypeImpl extends ReferenceTypeImpl { - /** - * The invocation result wrapper - * It is necessary because both ClassType and InterfaceType - * use their own type to represent the invocation result - */ - static interface InvocationResult { - ObjectReferenceImpl getException(); - ValueImpl getResult(); - } - - InvokableTypeImpl(VirtualMachine aVm, long aRef) { - super(aVm, aRef); - } - - /** - * Method invocation support. - * Shared by ClassType and InterfaceType - * @param threadIntf the thread in which to invoke. - * @param methodIntf method the {@link Method} to invoke. - * @param origArguments the list of {@link Value} arguments bound to the - * invoked method. Values from the list are assigned to arguments - * in the order they appear in the method signature. - * @param options the integer bit flag options. - * @return a {@link Value} mirror of the invoked method's return value. - * @throws java.lang.IllegalArgumentException if the method is not - * a member of this type, if the size of the argument list - * does not match the number of declared arguments for the method, or - * if the method is not static or is a static initializer. - * @throws {@link InvalidTypeException} if any argument in the - * argument list is not assignable to the corresponding method argument - * type. - * @throws ClassNotLoadedException if any argument type has not yet been loaded - * through the appropriate class loader. - * @throws IncompatibleThreadStateException if the specified thread has not - * been suspended by an event. - * @throws InvocationException if the method invocation resulted in - * an exception in the target VM. - * @throws InvalidTypeException If the arguments do not meet this requirement -- - * Object arguments must be assignment compatible with the argument - * type. This implies that the argument type must be - * loaded through the enclosing class's class loader. - * Primitive arguments must be either assignment compatible with the - * argument type or must be convertible to the argument type without loss - * of information. See JLS section 5.2 for more information on assignment - * compatibility. - * @throws VMCannotBeModifiedException if the VirtualMachine is read-only - see {@link VirtualMachine#canBeModified()}. - */ - final public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, - List origArguments, int options) - throws InvalidTypeException, - ClassNotLoadedException, - IncompatibleThreadStateException, - InvocationException { - validateMirror(threadIntf); - validateMirror(methodIntf); - validateMirrorsOrNulls(origArguments); - MethodImpl method = (MethodImpl) methodIntf; - ThreadReferenceImpl thread = (ThreadReferenceImpl) threadIntf; - validateMethodInvocation(method); - List arguments = method.validateAndPrepareArgumentsForInvoke(origArguments); - ValueImpl[] args = arguments.toArray(new ValueImpl[0]); - InvocationResult ret; - try { - PacketStream stream = sendInvokeCommand(thread, method, args, options); - ret = waitForReply(stream); - } catch (JDWPException exc) { - if (exc.errorCode() == JDWP.Error.INVALID_THREAD) { - throw new IncompatibleThreadStateException(); - } else { - throw exc.toJDIException(); - } - } - /* - * There is an implict VM-wide suspend at the conclusion - * of a normal (non-single-threaded) method invoke - */ - if ((options & ClassType.INVOKE_SINGLE_THREADED) == 0) { - vm.notifySuspend(); - } - if (ret.getException() != null) { - throw new InvocationException(ret.getException()); - } else { - return ret.getResult(); - } - } - - @Override - boolean isAssignableTo(ReferenceType type) { - ClassTypeImpl superclazz = (ClassTypeImpl) superclass(); - if (this.equals(type)) { - return true; - } else if ((superclazz != null) && superclazz.isAssignableTo(type)) { - return true; - } else { - List interfaces = interfaces(); - Iterator iter = interfaces.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); - if (interfaze.isAssignableTo(type)) { - return true; - } - } - return false; - } - } - - @Override - final void addVisibleMethods(Map methodMap, Set seenInterfaces) { - /* - * Add methods from - * parent types first, so that the methods in this class will - * overwrite them in the hash table - */ - Iterator iter = interfaces().iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); - if (!seenInterfaces.contains(interfaze)) { - interfaze.addVisibleMethods(methodMap, seenInterfaces); - seenInterfaces.add(interfaze); - } - } - ClassTypeImpl clazz = (ClassTypeImpl) superclass(); - if (clazz != null) { - clazz.addVisibleMethods(methodMap, seenInterfaces); - } - addToMethodMap(methodMap, methods()); - } - - final void addInterfaces(List list) { - List immediate = interfaces(); - list.addAll(interfaces()); - Iterator iter = immediate.iterator(); - while (iter.hasNext()) { - InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next(); - interfaze.addInterfaces(list); - } - ClassTypeImpl superclass = (ClassTypeImpl) superclass(); - if (superclass != null) { - superclass.addInterfaces(list); - } - } - - /** - * Returns all the implemented interfaces recursively - * @return A list of all the implemented interfaces (recursively) - */ - final List getAllInterfaces() { - List all = new ArrayList<>(); - addInterfaces(all); - return all; - } - - /** - * Shared implementation of {@linkplain ClassType#allMethods()} and - * {@linkplain InterfaceType#allMethods()} - * @return A list of all methods (recursively) - */ - public final List allMethods() { - ArrayList list = new ArrayList<>(methods()); - ClassType clazz = superclass(); - while (clazz != null) { - list.addAll(clazz.methods()); - clazz = clazz.superclass(); - } - /* - * Avoid duplicate checking on each method by iterating through - * duplicate-free allInterfaces() rather than recursing - */ - for (InterfaceType interfaze : getAllInterfaces()) { - list.addAll(interfaze.methods()); - } - return list; - } - - @Override - final List inheritedTypes() { - List inherited = new ArrayList<>(); - if (superclass() != null) { - inherited.add(0, superclass()); /* insert at front */ - } - for (ReferenceType rt : interfaces()) { - inherited.add(rt); - } - return inherited; - } - - private PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, - final MethodImpl method, - final ValueImpl[] args, - final int options) { - CommandSender sender = getInvokeMethodSender(thread, method, args, options); - PacketStream stream; - if ((options & ClassType.INVOKE_SINGLE_THREADED) != 0) { - stream = thread.sendResumingCommand(sender); - } else { - stream = vm.sendResumingCommand(sender); - } - return stream; - } - - private void validateMethodInvocation(Method method) - throws InvalidTypeException, - InvocationException { - if (!canInvoke(method)) { - throw new IllegalArgumentException("Invalid method"); - } - /* - * Method must be a static and not a static initializer - */ - if (!method.isStatic()) { - throw new IllegalArgumentException("Cannot invoke instance method on a class/interface type"); - } else if (method.isStaticInitializer()) { - throw new IllegalArgumentException("Cannot invoke static initializer"); - } - } - - /** - * A subclass will provide specific {@linkplain CommandSender} - * @param thread the current invocation thread - * @param method the method to invoke - * @param args the arguments to pass to the method - * @param options the integer bit flag options - * @return the specific {@literal CommandSender} instance - */ - abstract CommandSender getInvokeMethodSender(ThreadReferenceImpl thread, - MethodImpl method, - ValueImpl[] args, - int options); - - /** - * Waits for the reply to the last sent command - * @param stream the stream to listen for the reply on - * @return the {@linkplain InvocationResult} instance - * @throws JDWPException when something goes wrong in JDWP - */ - abstract InvocationResult waitForReply(PacketStream stream) throws JDWPException; - - /** - * Get the {@linkplain ReferenceType} superclass - * @return the superclass or null - */ - abstract ClassType superclass(); - - /** - * Get the implemented/extended interfaces - * @return the list of implemented/extended interfaces - */ - abstract List interfaces(); - - /** - * Checks the provided method whether it can be invoked - * @param method the method to check - * @return {@code TRUE} if the implementation knows how to invoke the method, - * {@code FALSE} otherwise - */ - abstract boolean canInvoke(Method method); -} diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Tue Apr 29 14:37:02 2014 +0200 @@ -187,13 +187,6 @@ return isModifierSet(VMModifiers.ABSTRACT); } - public boolean isDefault() { - return !isModifierSet(VMModifiers.ABSTRACT) && - !isModifierSet(VMModifiers.STATIC) && - !isModifierSet(VMModifiers.PRIVATE) && - declaringType() instanceof InterfaceType; - } - public boolean isSynchronized() { return isModifierSet(VMModifiers.SYNCHRONIZED); } diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java Tue Apr 29 14:37:02 2014 +0200 @@ -277,6 +277,7 @@ void validateMethodInvocation(Method method, int options) throws InvalidTypeException, InvocationException { + /* * Method must be in this object's class, a superclass, or * implemented interface @@ -286,19 +287,6 @@ throw new IllegalArgumentException("Invalid method"); } - if (declType instanceof ClassTypeImpl) { - validateClassMethodInvocation(method, options); - } else if (declType instanceof InterfaceTypeImpl) { - validateIfaceMethodInvocation(method, options); - } else { - throw new InvalidTypeException(); - } - } - - void validateClassMethodInvocation(Method method, int options) - throws InvalidTypeException, - InvocationException { - ClassTypeImpl clazz = invokableReferenceType(method); /* @@ -312,7 +300,9 @@ * For nonvirtual invokes, method must have a body */ if ((options & INVOKE_NONVIRTUAL) != 0) { - if (method.isAbstract()) { + if (method.declaringType() instanceof InterfaceType) { + throw new IllegalArgumentException("Interface method"); + } else if (method.isAbstract()) { throw new IllegalArgumentException("Abstract method"); } } @@ -334,7 +324,7 @@ */ Method invoker = clazz.concreteMethodByName(method.name(), method.signature()); - // invoker is supposed to be non-null under normal circumstances + // isAssignableFrom check above guarantees non-null invokedClass = (ClassTypeImpl)invoker.declaringType(); } /* The above code is left over from previous versions. @@ -342,17 +332,6 @@ */ } - void validateIfaceMethodInvocation(Method method, int options) - throws InvalidTypeException, - InvocationException { - /* - * Only default methods allowed for nonvirtual invokes - */ - if (!method.isDefault()) { - throw new IllegalArgumentException("Not a default method"); - } - } - PacketStream sendInvokeCommand(final ThreadReferenceImpl thread, final ClassTypeImpl refType, final MethodImpl method, @@ -391,10 +370,7 @@ ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf; if (method.isStatic()) { - if (referenceType() instanceof InterfaceType) { - InterfaceType type = (InterfaceType)referenceType(); - return type.invokeMethod(thread, method, origArguments, options); - } else if (referenceType() instanceof ClassType) { + if (referenceType() instanceof ClassType) { ClassType type = (ClassType)referenceType(); return type.invokeMethod(thread, method, origArguments, options); } else { diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java --- a/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Tue Apr 29 13:23:08 2014 +0100 +++ b/jdk/src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Tue Apr 29 14:37:02 2014 +0200 @@ -48,7 +48,7 @@ private ResourceBundle messages = null; private int vmSequenceNumber = 0; private static final int majorVersion = 1; - private static final int minorVersion = 8; + private static final int minorVersion = 6; private static final Object lock = new Object(); private static VirtualMachineManagerImpl vmm; diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/test/com/sun/jdi/EvalInterfaceStatic.sh --- a/jdk/test/com/sun/jdi/EvalInterfaceStatic.sh Tue Apr 29 13:23:08 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2014, 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 8031195 -# @summary JDB allows evaluation of calls to static interface methods -# @author Jaroslav Bachorik -# -# @run shell/timeout=300 EvalInterfaceStatic.sh - -# The test exercises the ability to invoke static methods on interfaces. -# Static interface methods are a new feature added in JDK8. -# -# The test makes sure that it is, at all, possible to invoke an interface -# static method and that the static methods are not inherited by extending -# interfaces. - -classname=EvalStaticInterfaces - -createJavaFile() -{ - cat < $classname.java.1 -public interface $classname { - static String staticMethod1() { - return "base:staticMethod1"; - } - - static String staticMethod2() { - return "base:staticMethod2"; - } - - public static void main(String[] args) { - // prove that these work - System.out.println("base staticMethod1(): " + $classname.staticMethod1()); - System.out.println("base staticMethod2(): " + $classname.staticMethod2()); - System.out.println("overridden staticMethod2(): " + Extended$classname.staticMethod2()); - System.out.println("base staticMethod3(): " + Extended$classname.staticMethod3()); - - gus(); - } - - static void gus() { - int x = 0; // @1 breakpoint - } -} - -interface Extended$classname extends $classname { - static String staticMethod2() { - return "extended:staticMethod2"; - } - - static String staticMethod3() { - return "extended:staticMethod3"; - } -} - - - -EOF -} - -# drive jdb by sending cmds to it and examining its output -dojdbCmds() -{ - setBkpts @1 - runToBkpt @1 - - cmd eval "$classname.staticMethod1()" - jdbFailIfNotPresent "base:staticMethod1" 2 - - cmd eval "$classname.staticMethod2()" - jdbFailIfNotPresent "base:staticMethod2" 2 - - cmd eval "Extended$classname.staticMethod1()" - jdbFailIfPresent "base:staticMethod1" 2 - - cmd eval "Extended$classname.staticMethod2()" - jdbFailIfNotPresent "extended:staticMethod2" 2 - - cmd eval "Extended$classname.staticMethod3()" - jdbFailIfNotPresent "extended:staticMethod3" 2 -} - - -mysetup() -{ - if [ -z "$TESTSRC" ] ; then - TESTSRC=. - fi - - for ii in . $TESTSRC $TESTSRC/.. ; do - if [ -r "$ii/ShellScaffold.sh" ] ; then - . $ii/ShellScaffold.sh - break - fi - done -} - -# You could replace this next line with the contents -# of ShellScaffold.sh and this script will run just the same. -mysetup - -runit -pass diff -r dda4c98ed5e9 -r 5d05d4c0de7f jdk/test/com/sun/jdi/InterfaceMethodsTest.java --- a/jdk/test/com/sun/jdi/InterfaceMethodsTest.java Tue Apr 29 13:23:08 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,422 +0,0 @@ -/* - * Copyright (c) 2014, 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 8031195 - * @summary JDI: Add support for static and default methods in interfaces - * - * @run build TestScaffold VMConnection TargetListener TargetAdapter - * @run build InterfaceMethodsTest - * @run main InterfaceMethodsTest - */ -import com.sun.jdi.*; -import com.sun.jdi.event.*; -import java.util.Collections; - -public class InterfaceMethodsTest extends TestScaffold { - private static final int RESULT_A = 1; - private static final int RESULT_B = 1; - private static final int RESULT_TARGET = 1; - static interface InterfaceA { - static int staticMethodA() { - System.out.println("-InterfaceA: static interface method A-"); - return RESULT_A; - } - static int staticMethodB() { - System.out.println("-InterfaceA: static interface method B-"); - return RESULT_A; - } - default int defaultMethodA() { - System.out.println("-InterfaceA: default interface method A-"); - return RESULT_A; - } - default int defaultMethodB() { - System.out.println("-InterfaceA: default interface method B-"); - return RESULT_A; - } - default int defaultMethodC() { - System.out.println("-InterfaceA: default interface method C-"); - return RESULT_A; - } - - int implementedMethod(); - } - - static interface InterfaceB extends InterfaceA { - @Override - default int defaultMethodC() { - System.out.println("-InterfaceB: overridden default interface method C-"); - return RESULT_B; - } - default int defaultMethodD() { - System.out.println("-InterfaceB: default interface method D-"); - return RESULT_B; - } - - static int staticMethodB() { - System.out.println("-InterfaceB: overridden static interface method B-"); - return RESULT_B; - } - - static int staticMethodC() { - System.out.println("-InterfaceB: static interface method C-"); - return RESULT_B; - } - } - - final static class TargetClass implements InterfaceB { - public int classMethod() { - System.out.println("-TargetClass: class only method-"); - return RESULT_TARGET; - } - - @Override - public int implementedMethod() { - System.out.println("-TargetClass: implemented non-default interface method-"); - return RESULT_TARGET; - } - - @Override - public int defaultMethodB() { - System.out.println("-TargetClass: overridden default interface method D"); - - return RESULT_TARGET; - } - - public static void main(String[] args) { - TargetClass tc = new TargetClass(); - tc.doTests(tc); - } - - private void doTests(TargetClass ref) { - // break - } - } - - public InterfaceMethodsTest(String[] args) { - super(args); - } - - public static void main(String[] args) throws Exception { - new InterfaceMethodsTest(args).startTests(); - } - - private static final String TEST_CLASS_NAME = InterfaceMethodsTest.class.getName().replace('.', '/'); - private static final String TARGET_CLASS_NAME = TargetClass.class.getName().replace('.', '/'); - private static final String INTERFACEA_NAME = InterfaceA.class.getName().replace('.', '/'); - private static final String INTERFACEB_NAME = InterfaceB.class.getName().replace('.', '/'); - - protected void runTests() throws Exception { - /* - * Get to the top of main() - * to determine targetClass and mainThread - */ - BreakpointEvent bpe = startToMain(TARGET_CLASS_NAME); - - bpe = resumeTo(TARGET_CLASS_NAME, "doTests", "(L" + TARGET_CLASS_NAME +";)V"); - - mainThread = bpe.thread(); - - StackFrame frame = mainThread.frame(0); - ObjectReference thisObject = frame.thisObject(); - ObjectReference ref = (ObjectReference)frame.getArgumentValues().get(0); - - ReferenceType targetClass = bpe.location().declaringType(); - testImplementationClass(targetClass, thisObject); - - testInterfaceA(ref); - - testInterfaceB(ref); - - /* - * resume the target listening for events - */ - listenUntilVMDisconnect(); - - /* - * deal with results of test - * if anything has called failure("foo") testFailed will be true - */ - if (!testFailed) { - println("InterfaceMethodsTest: passed"); - } else { - throw new Exception("InterfaceMethodsTest: failed"); - } - } - - private void testInterfaceA(ObjectReference ref) { - // Test non-virtual calls on InterfaceA - - ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0); - /* Default method calls */ - - // invoke the InterfaceA's "defaultMethodA" - testInvokePos(ifaceClass, ref, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A)); - - // invoke the InterfaceA's "defaultMethodB" - testInvokePos(ifaceClass, ref, "defaultMethodB", "()I", vm().mirrorOf(RESULT_A)); - - // invoke the InterfaceA's "defaultMethodC" - testInvokePos(ifaceClass, ref, "defaultMethodC", "()I", vm().mirrorOf(RESULT_A)); - - // "defaultMethodD" from InterfaceB is not accessible from here - testInvokeNeg(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B), - "Attempted to invoke non-existing method"); - - // trying to invoke the asbtract method "implementedMethod" - testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(TARGET_CLASS_NAME), - "Invocation of non-default methods is not supported"); - - - /* Static method calls */ - - // invoke interface static method A - testInvokePos(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A)); - - // try to invoke static method A on the instance - testInvokePos(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A)); - - // invoke interface static method B - testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_A)); - - // try to invoke static method B on the instance - testInvokePos(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_A)); - } - - private void testInterfaceB(ObjectReference ref) { - // Test non-virtual calls on InterfaceB - ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEB_NAME).get(0); - - /* Default method calls */ - - // invoke the inherited "defaultMethodA" - testInvokePos(ifaceClass, ref, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A)); - - // invoke the inherited "defaultMethodB" - testInvokePos(ifaceClass, ref, "defaultMethodB", "()I", vm().mirrorOf(RESULT_A)); - - // invoke the inherited and overridden "defaultMethodC" - testInvokePos(ifaceClass, ref, "defaultMethodC", "()I", vm().mirrorOf(RESULT_B)); - - // invoke InterfaceB only "defaultMethodD" - testInvokePos(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B)); - - // "implementedMethod" is not present in InterfaceB - testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET), - "Invocation of non-default methods is not supported"); - - - /* Static method calls*/ - - // "staticMethodA" must not be inherited by InterfaceB - testInvokeNeg(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), - "Static interface methods are not inheritable"); - - // however it is possible to call "staticMethodA" on the actual instance - testInvokeNeg(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), - "Static interface methods are not inheritable"); - - // "staticMethodB" is overridden in InterfaceB - testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_B)); - - // the instance invokes the overriden form of "staticMethodB" from InterfaceB - testInvokePos(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_B)); - - // "staticMethodC" is present only in InterfaceB - testInvokePos(ifaceClass, null, "staticMethodC", "()I", vm().mirrorOf(RESULT_B)); - - // "staticMethodC" should be reachable from the instance too - testInvokePos(ifaceClass, ref, "staticMethodC", "()I", vm().mirrorOf(RESULT_B)); - } - - private void testImplementationClass(ReferenceType targetClass, ObjectReference thisObject) { - // Test invocations on the implementation object - - /* Default method calls */ - - // "defaultMethodA" is accessible and not overridden - testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_TARGET)); - - // "defaultMethodB" is accessible and overridden in TargetClass - testInvokePos(targetClass, thisObject, "defaultMethodB", "()I", vm().mirrorOf(RESULT_TARGET)); - - // "defaultMethodC" is accessible and overridden in InterfaceB - testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_TARGET)); - - // "defaultMethodD" is accessible - testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_TARGET)); - - - /* Non-default instance method calls */ - - // "classMethod" declared in TargetClass is accessible - testInvokePos(targetClass, thisObject, "classMethod", "()I", vm().mirrorOf(RESULT_TARGET)); - - // the abstract "implementedMethod" has been implemented in TargetClass - testInvokePos(targetClass, thisObject, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET)); - - - /* Static method calls */ - - // All the static methods declared by the interfaces are not reachable from the instance of the implementor class - testInvokeNeg(targetClass, thisObject, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), - "Static interface methods are not inheritable"); - - testInvokeNeg(targetClass, thisObject, "staticMethodB", "()I", vm().mirrorOf(RESULT_B), - "Static interface methods are not inheritable"); - - testInvokeNeg(targetClass, thisObject, "staticMethodC", "()I", vm().mirrorOf(RESULT_B), - "Static interface methods are not inheritable"); - - // All the static methods declared by the interfaces are not reachable through the implementor class - testInvokeNeg(targetClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A), - "Static interface methods are not inheritable"); - - testInvokeNeg(targetClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_B), - "Static interface methods are not inheritable"); - - testInvokeNeg(targetClass, null, "staticMethodC", "()I", vm().mirrorOf(RESULT_B), - "Static interface methods are not inheritable"); - } - - private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName, - String methodSig, Value value) { - logInvocation(ref, methodName, methodSig, targetClass); - try { - invoke(targetClass, ref, methodName, methodSig, value); - System.err.println("--- PASSED"); - } catch (Exception e) { - System.err.println("--- FAILED"); - failure("FAILED: Invocation failed with error message " + e.getLocalizedMessage()); - } - } - - private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName, - String methodSig, Value value, String msg) { - logInvocation(ref, methodName, methodSig, targetClass); - try { - invoke(targetClass, ref, methodName, methodSig, value); - System.err.println("--- FAILED"); - failure("FAILED: " + msg); - } catch (Exception e) { - System.err.println("--- PASSED"); - - } - } - - private void invoke(ReferenceType targetClass, ObjectReference ref, String methodName, - String methodSig, Value value) - throws Exception { - Method method = getMethod(targetClass, methodName, methodSig); - if (method == null) { - throw new Exception("Can't find method: " + methodName + " for class = " + targetClass); - } - - println("Invoking " + (method.isAbstract() ? "abstract " : " ") + "method: " + method); - - Value returnValue = null; - if (ref != null) { - returnValue = invokeInstance(ref, method); - } else { - returnValue = invokeStatic(targetClass, method); - } - - println(" return val = " + returnValue); - // It has to be the same value as what we passed in! - if (returnValue.equals(value)) { - println(" " + method.name() + " return value matches: " - + value); - } else { - if (value != null) { - throw new Exception(method.name() + " returned: " + returnValue + - " expected: " + value ); - } else { - println(" " + method.name() + " return value : " + returnValue); - } - - } - } - - private Value invokeInstance(ObjectReference ref, Method method) throws Exception { - return ref.invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL); - } - - private Value invokeStatic(ReferenceType refType, Method method) throws Exception { - if (refType instanceof ClassType) { - return ((ClassType)refType).invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL); - } else { - return ((InterfaceType)refType).invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL); - } - } - - private Method getMethod(ReferenceType rt, String name, String signature) { - if (rt == null) return null; - Method m = findMethod(rt, name, signature); - if (m == null) { - if (rt instanceof ClassType) { - for (Object ifc : ((ClassType)rt).interfaces()) { - m = getMethod((ReferenceType)ifc, name, signature); - if (m != null) { - break; - } - } - if (m == null) { - m = getMethod(((ClassType)rt).superclass(), name, signature); - } else { - if (m.isStatic()) { - // interface static methods are not inherited - m = null; - } - } - } else if (rt instanceof InterfaceType) { - for(Object ifc : ((InterfaceType)rt).superinterfaces()) { - m = getMethod((ReferenceType)ifc, name, signature); - if (m != null) { - if (m.isStatic()) { - // interface static methods are not inherited - m = null; - } - break; - } - } - } - } - - return m; - } - - private void logInvocation(ObjectReference ref, String methodName, String methodSig, ReferenceType targetClass) { - if (ref != null) { - System.err.println("Invoking: " + ref.referenceType().name() + "." + - methodName + methodSig + " with target of type " + - targetClass.name()); - } else { - System.err.println("Invoking static : " + targetClass.name() + "." + - methodName + methodSig); - } - } -} - - -