--- 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. "
- "<p>Since JDWP version 1.8 "
- "<p>"
- "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. "
- "<p>"
- "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. "
- "<p>"
- "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. "
- "<p>"
- "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. "
- "<p>"
- "The resumption of other threads during the invoke can be prevented "
- "by specifying the INVOKE_SINGLE_THREADED "
- "bit flag in the <code>options</code> 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. "
- "<p>"
- "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 <a href=\"#JDWP_InvokeOptions\">options</a>")
- )
- (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 @@
"<p>"
"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)
--- 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
-};
--- 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[];
--- 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)
--- 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;
--- 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 {
--- 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 @@
* <p>
* 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 @@
* <p>
* 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 @@
* <p>
* 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
--- 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<ClassType> 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.
- * <p>
- * 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}.
- * <p>
- * 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.
- * <p>
- * 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
- * <cite>The Java™ Language Specification</cite>
- * for more information on assignment compatibility.
- * <p>
- * 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.
- * <p>
- * The resumption of other threads during the invocation can be prevented
- * by specifying the {@link #INVOKE_SINGLE_THREADED}
- * bit flag in the <code>options</code> 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.
- * <p>
- * 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<? extends Value> arguments, int options)
- throws InvalidTypeException,
- ClassNotLoadedException,
- IncompatibleThreadStateException,
- InvocationException;
}
--- 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 <code>true</code> if the method is declared default;
- * false otherwise
- *
- * @since 1.8
- */
- boolean isDefault();
-
- /**
* Determine if this method is synchronized.
*
* @return <code>true</code> if the method is declared synchronized;
--- 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 <code>options</code>
* 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 <code>super</code> 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 <code>super</code> keyword in
+ * the Java programming language.
* <p>
* 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.
--- 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());
--- 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<InterfaceType> interfaces() {
if (interfaces == null) {
interfaces = getInterfaces();
@@ -91,9 +72,26 @@
return interfaces;
}
- @Override
- public List<InterfaceType> allInterfaces() {
- return getAllInterfaces();
+ void addInterfaces(List<InterfaceType> list) {
+ List<InterfaceType> immediate = interfaces();
+ list.addAll(interfaces());
+
+ Iterator<InterfaceType> 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<InterfaceType> allInterfaces() {
+ List<InterfaceType> all = new ArrayList<InterfaceType>();
+ addInterfaces(all);
+ return all;
}
public List<ClassType> 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<? extends Value> 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<? extends Value> 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<? extends Value> origArguments,
@@ -245,6 +311,58 @@
return method;
}
+ public List<Method> allMethods() {
+ ArrayList<Method> list = new ArrayList<Method>(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<ReferenceType> inheritedTypes() {
+ List<ReferenceType> inherited = new ArrayList<ReferenceType>();
+ 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<String, Method> methodMap, Set<InterfaceType> seenInterfaces) {
+ /*
+ * Add methods from
+ * parent types first, so that the methods in this class will
+ * overwrite them in the hash table
+ */
+
+ Iterator<InterfaceType> 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<InterfaceType> interfaces = interfaces();
+ Iterator<InterfaceType> 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);
- }
}
--- 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<List<InterfaceType>> superinterfacesRef = null;
@@ -98,6 +81,102 @@
return implementors;
}
+ @Override
+ void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> 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<Method> allMethods() {
+ ArrayList<Method> list = new ArrayList<Method>(methods());
+
+ /*
+ * It's more efficient if don't do this
+ * recursively.
+ */
+ for (InterfaceType interfaze : allSuperinterfaces()) {
+ list.addAll(interfaze.methods());
+ }
+
+ return list;
+ }
+
+ List<InterfaceType> allSuperinterfaces() {
+ ArrayList<InterfaceType> list = new ArrayList<InterfaceType>();
+ addSuperinterfaces(list);
+ return list;
+ }
+
+ void addSuperinterfaces(List<InterfaceType> 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<InterfaceType> immediate = new ArrayList<InterfaceType>(superinterfaces());
+ Iterator<InterfaceType> 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<InterfaceType> 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<InterfaceType> 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
+}
--- 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<? extends Value> 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<? extends Value> 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<InterfaceType> interfaces = interfaces();
- Iterator<InterfaceType> iter = interfaces.iterator();
- while (iter.hasNext()) {
- InterfaceTypeImpl interfaze = (InterfaceTypeImpl) iter.next();
- if (interfaze.isAssignableTo(type)) {
- return true;
- }
- }
- return false;
- }
- }
-
- @Override
- final void addVisibleMethods(Map<String, Method> methodMap, Set<InterfaceType> seenInterfaces) {
- /*
- * Add methods from
- * parent types first, so that the methods in this class will
- * overwrite them in the hash table
- */
- Iterator<InterfaceType> 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<InterfaceType> list) {
- List<InterfaceType> immediate = interfaces();
- list.addAll(interfaces());
- Iterator<InterfaceType> 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<InterfaceType> getAllInterfaces() {
- List<InterfaceType> 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<Method> allMethods() {
- ArrayList<Method> 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<ReferenceType> inheritedTypes() {
- List<ReferenceType> 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<InterfaceType> 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);
-}
--- 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);
}
--- 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 {
--- 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;
--- 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 <<EOF > $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
--- 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);
- }
- }
-}
-
-
-