Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
7f066bb3
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
7f066bb3
编写于
4月 30, 2014
作者:
J
jbachorik
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8042123: Support default and static interface methods in JDI, JDWP and JDB
Reviewed-by: sla, sspitsyn
上级
4fa4eed3
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
1284 addition
and
298 deletion
+1284
-298
make/data/jdwp/jdwp.spec
make/data/jdwp/jdwp.spec
+83
-3
src/share/back/InterfaceTypeImpl.c
src/share/back/InterfaceTypeImpl.c
+39
-0
src/share/back/InterfaceTypeImpl.h
src/share/back/InterfaceTypeImpl.h
+25
-0
src/share/back/VirtualMachineImpl.c
src/share/back/VirtualMachineImpl.c
+1
-1
src/share/back/debugDispatch.c
src/share/back/debugDispatch.c
+2
-0
src/share/back/util.c
src/share/back/util.c
+2
-0
src/share/classes/com/sun/jdi/ClassType.java
src/share/classes/com/sun/jdi/ClassType.java
+6
-6
src/share/classes/com/sun/jdi/InterfaceType.java
src/share/classes/com/sun/jdi/InterfaceType.java
+119
-0
src/share/classes/com/sun/jdi/Method.java
src/share/classes/com/sun/jdi/Method.java
+12
-0
src/share/classes/com/sun/jdi/ObjectReference.java
src/share/classes/com/sun/jdi/ObjectReference.java
+6
-6
src/share/classes/com/sun/tools/example/debug/expr/LValue.java
...hare/classes/com/sun/tools/example/debug/expr/LValue.java
+3
-0
src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
+45
-181
src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
+50
-94
src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
+305
-0
src/share/classes/com/sun/tools/jdi/MethodImpl.java
src/share/classes/com/sun/tools/jdi/MethodImpl.java
+7
-0
src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java
src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java
+30
-6
src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
.../classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
+1
-1
test/com/sun/jdi/EvalInterfaceStatic.sh
test/com/sun/jdi/EvalInterfaceStatic.sh
+126
-0
test/com/sun/jdi/InterfaceMethodsTest.java
test/com/sun/jdi/InterfaceMethodsTest.java
+422
-0
未找到文件。
make/data/jdwp/jdwp.spec
浏览文件 @
7f066bb3
...
...
@@ -1147,7 +1147,8 @@ JDWP "Java(tm) Debug Wire Protocol"
(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 method.")
(Error INVALID_METHODID "methodID is not the ID of a static method in "
"this class type or one of its superclasses.")
(Error INVALID_THREAD)
(Error THREAD_NOT_SUSPENDED)
(Error VM_DEAD)
...
...
@@ -1250,6 +1251,83 @@ JDWP "Java(tm) Debug Wire Protocol"
)
)
(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
...
...
@@ -1543,7 +1621,7 @@ JDWP "Java(tm) Debug Wire Protocol"
"<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 command. "
"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 "
...
...
@@ -1586,7 +1664,9 @@ JDWP "Java(tm) Debug Wire Protocol"
(Error INVALID_OBJECT)
(Error INVALID_CLASS "clazz is not the ID of a reference "
"type.")
(Error INVALID_METHODID "methodID is not the ID of a method.")
(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_THREAD)
(Error THREAD_NOT_SUSPENDED)
(Error VM_DEAD)
...
...
src/share/back/InterfaceTypeImpl.c
0 → 100644
浏览文件 @
7f066bb3
/*
* 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
};
src/share/back/InterfaceTypeImpl.h
0 → 100644
浏览文件 @
7f066bb3
/*
* 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
[];
src/share/back/VirtualMachineImpl.c
浏览文件 @
7f066bb3
...
...
@@ -36,7 +36,7 @@
static
char
*
versionName
=
"Java Debug Wire Protocol (Reference Implementation)"
;
static
int
majorVersion
=
1
;
/* JDWP major version */
static
int
minorVersion
=
6
;
/* JDWP minor version */
static
int
minorVersion
=
8
;
/* JDWP minor version */
static
jboolean
version
(
PacketInputStream
*
in
,
PacketOutputStream
*
out
)
...
...
src/share/back/debugDispatch.c
浏览文件 @
7f066bb3
...
...
@@ -29,6 +29,7 @@
#include "VirtualMachineImpl.h"
#include "ReferenceTypeImpl.h"
#include "ClassTypeImpl.h"
#include "InterfaceTypeImpl.h"
#include "ArrayTypeImpl.h"
#include "FieldImpl.h"
#include "MethodImpl.h"
...
...
@@ -67,6 +68,7 @@ debugDispatch_initialize(void)
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
;
...
...
src/share/back/util.c
浏览文件 @
7f066bb3
...
...
@@ -591,6 +591,8 @@ sharedInvoke(PacketInputStream *in, PacketOutputStream *out)
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
{
...
...
src/share/classes/com/sun/jdi/ClassType.java
浏览文件 @
7f066bb3
...
...
@@ -103,7 +103,7 @@ public interface ClassType extends ReferenceType {
* <p>
* Object values must be assignment compatible with the field type
* (This implies that the field type must be loaded through the
* enclosing class'
s
class loader). Primitive values must be
* enclosing class' 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 @@ public interface ClassType extends ReferenceType {
* <p>
* 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
* 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,
...
...
@@ -216,7 +216,7 @@ public interface ClassType extends ReferenceType {
* @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 argu
em
nts for the method, or
* does not match the number of declared argu
me
nts 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 @@ public interface ClassType extends ReferenceType {
* @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.
* 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
...
...
@@ -267,7 +267,7 @@ public interface ClassType extends ReferenceType {
* <p>
* 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
* 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,
...
...
@@ -335,7 +335,7 @@ public interface ClassType extends ReferenceType {
* @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.
* 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
...
...
src/share/classes/com/sun/jdi/InterfaceType.java
浏览文件 @
7f066bb3
...
...
@@ -79,4 +79,123 @@ public interface InterfaceType extends ReferenceType {
* 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
*/
default
Value
invokeMethod
(
ThreadReference
thread
,
Method
method
,
List
<?
extends
Value
>
arguments
,
int
options
)
throws
InvalidTypeException
,
ClassNotLoadedException
,
IncompatibleThreadStateException
,
InvocationException
{
throw
new
UnsupportedOperationException
();
}
}
src/share/classes/com/sun/jdi/Method.java
浏览文件 @
7f066bb3
...
...
@@ -137,6 +137,18 @@ public interface Method extends TypeComponent, Locatable, Comparable<Method> {
*/
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
*/
default
boolean
isDefault
()
{
throw
new
UnsupportedOperationException
();
}
/**
* Determine if this method is synchronized.
*
...
...
src/share/classes/com/sun/jdi/ObjectReference.java
浏览文件 @
7f066bb3
...
...
@@ -194,10 +194,10 @@ public interface ObjectReference extends Value {
* {@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
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.
* 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.
* <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 @@ public interface ObjectReference extends Value {
* @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 argu
em
nts for the method,
* does not match the number of declared argu
me
nts 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
n
interface member.
* either abstract or a
non-default
interface member.
* @throws {@link InvalidTypeException} if any argument in the
* argument list is not assignable to the corresponding method argument
* type.
...
...
src/share/classes/com/sun/tools/example/debug/expr/LValue.java
浏览文件 @
7f066bb3
...
...
@@ -559,6 +559,9 @@ abstract class LValue {
}
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
());
...
...
src/share/classes/com/sun/tools/jdi/ClassTypeImpl.java
浏览文件 @
7f066bb3
...
...
@@ -29,9 +29,27 @@ import com.sun.jdi.*;
import
java.util.*
;
public
class
ClassTypeImpl
extends
Referenc
eTypeImpl
final
public
class
ClassTypeImpl
extends
Invokabl
eTypeImpl
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
;
...
...
@@ -65,6 +83,7 @@ public class ClassTypeImpl extends ReferenceTypeImpl
return
superclass
;
}
@Override
public
List
<
InterfaceType
>
interfaces
()
{
if
(
interfaces
==
null
)
{
interfaces
=
getInterfaces
();
...
...
@@ -72,26 +91,9 @@ public class ClassTypeImpl extends ReferenceTypeImpl
return
interfaces
;
}
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
;
@Override
public
List
<
InterfaceType
>
allInterfaces
()
{
return
getAllInterfaces
();
}
public
List
<
ClassType
>
subclasses
()
{
...
...
@@ -159,28 +161,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
}
}
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
,
...
...
@@ -203,52 +183,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
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
,
...
...
@@ -311,58 +245,6 @@ public class ClassTypeImpl extends ReferenceTypeImpl
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
{
...
...
@@ -382,51 +264,33 @@ public class ClassTypeImpl extends ReferenceTypeImpl
}
}
@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
);
}
public
String
toString
()
{
return
"class "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
}
addToMethodMap
(
methodMap
,
methods
());
@Override
CommandSender
getInvokeMethodSender
(
ThreadReferenceImpl
thread
,
MethodImpl
method
,
ValueImpl
[]
args
,
int
options
)
{
return
()
->
JDWP
.
ClassType
.
InvokeMethod
.
enqueueCommand
(
vm
,
ClassTypeImpl
.
this
,
thread
,
method
.
ref
(),
args
,
options
);
}
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
InvocationResult
waitForReply
(
PacketStream
stream
)
throws
JDWPException
{
return
new
IResult
(
JDWP
.
ClassType
.
InvokeMethod
.
waitForReply
(
vm
,
stream
));
}
public
String
toString
()
{
return
"class "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
@Override
boolean
canInvoke
(
Method
method
)
{
// Method must be in this class or a superclass.
return
((
ReferenceTypeImpl
)
method
.
declaringType
()).
isAssignableFrom
(
this
);
}
}
src/share/classes/com/sun/tools/jdi/InterfaceTypeImpl.java
浏览文件 @
7f066bb3
...
...
@@ -29,14 +29,31 @@ import com.sun.jdi.*;
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
;
public
class
InterfaceTypeImpl
extends
ReferenceTypeImpl
implements
InterfaceType
{
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
;
}
}
private
SoftReference
<
List
<
InterfaceType
>>
superinterfacesRef
=
null
;
...
...
@@ -81,107 +98,46 @@ public class InterfaceTypeImpl extends ReferenceTypeImpl
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
boolean
isInitialized
()
{
return
isPrepared
();
}
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
;
public
String
toString
()
{
return
"interface "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
}
List
<
InterfaceType
>
allSuperinterfaces
()
{
ArrayList
<
InterfaceType
>
list
=
new
ArrayList
<
InterfaceType
>();
addSuperinterfaces
(
list
);
return
list
;
@Override
InvocationResult
waitForReply
(
PacketStream
stream
)
throws
JDWPException
{
return
new
IResult
(
JDWP
.
InterfaceType
.
InvokeMethod
.
waitForReply
(
vm
,
stream
));
}
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
);
}
@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
);
}
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
;
}
@Override
ClassType
superclass
()
{
return
null
;
}
List
<
InterfaceType
>
inheritedTypes
()
{
@Override
List
<
InterfaceType
>
interfaces
()
{
return
superinterfaces
();
}
public
boolean
isInitialized
()
{
return
isPrepared
();
}
public
String
toString
()
{
return
"interface "
+
name
()
+
" ("
+
loaderString
()
+
")"
;
@Override
boolean
canInvoke
(
Method
method
)
{
// method must be directly in this interface
return
this
.
equals
(
method
.
declaringType
());
}
}
}
\ No newline at end of file
src/share/classes/com/sun/tools/jdi/InvokableTypeImpl.java
0 → 100644
浏览文件 @
7f066bb3
/*
* 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
);
}
src/share/classes/com/sun/tools/jdi/MethodImpl.java
浏览文件 @
7f066bb3
...
...
@@ -187,6 +187,13 @@ public abstract class MethodImpl extends TypeComponentImpl
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
);
}
...
...
src/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java
浏览文件 @
7f066bb3
...
...
@@ -277,7 +277,6 @@ public class ObjectReferenceImpl extends ValueImpl
void
validateMethodInvocation
(
Method
method
,
int
options
)
throws
InvalidTypeException
,
InvocationException
{
/*
* Method must be in this object's class, a superclass, or
* implemented interface
...
...
@@ -287,6 +286,19 @@ public class ObjectReferenceImpl extends ValueImpl
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
);
/*
...
...
@@ -300,9 +312,7 @@ public class ObjectReferenceImpl extends ValueImpl
* For nonvirtual invokes, method must have a body
*/
if
((
options
&
INVOKE_NONVIRTUAL
)
!=
0
)
{
if
(
method
.
declaringType
()
instanceof
InterfaceType
)
{
throw
new
IllegalArgumentException
(
"Interface method"
);
}
else
if
(
method
.
isAbstract
())
{
if
(
method
.
isAbstract
())
{
throw
new
IllegalArgumentException
(
"Abstract method"
);
}
}
...
...
@@ -324,7 +334,7 @@ public class ObjectReferenceImpl extends ValueImpl
*/
Method
invoker
=
clazz
.
concreteMethodByName
(
method
.
name
(),
method
.
signature
());
// i
sAssignableFrom check above guarantees non-null
// i
nvoker is supposed to be non-null under normal circumstances
invokedClass
=
(
ClassTypeImpl
)
invoker
.
declaringType
();
}
/* The above code is left over from previous versions.
...
...
@@ -332,6 +342,17 @@ public class ObjectReferenceImpl extends ValueImpl
*/
}
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
,
...
...
@@ -370,7 +391,10 @@ public class ObjectReferenceImpl extends ValueImpl
ThreadReferenceImpl
thread
=
(
ThreadReferenceImpl
)
threadIntf
;
if
(
method
.
isStatic
())
{
if
(
referenceType
()
instanceof
ClassType
)
{
if
(
referenceType
()
instanceof
InterfaceType
)
{
InterfaceType
type
=
(
InterfaceType
)
referenceType
();
return
type
.
invokeMethod
(
thread
,
method
,
origArguments
,
options
);
}
else
if
(
referenceType
()
instanceof
ClassType
)
{
ClassType
type
=
(
ClassType
)
referenceType
();
return
type
.
invokeMethod
(
thread
,
method
,
origArguments
,
options
);
}
else
{
...
...
src/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java
浏览文件 @
7f066bb3
...
...
@@ -48,7 +48,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManagerService {
private
ResourceBundle
messages
=
null
;
private
int
vmSequenceNumber
=
0
;
private
static
final
int
majorVersion
=
1
;
private
static
final
int
minorVersion
=
6
;
private
static
final
int
minorVersion
=
8
;
private
static
final
Object
lock
=
new
Object
();
private
static
VirtualMachineManagerImpl
vmm
;
...
...
test/com/sun/jdi/EvalInterfaceStatic.sh
0 → 100644
浏览文件 @
7f066bb3
#!/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
test/com/sun/jdi/InterfaceMethodsTest.java
0 → 100644
浏览文件 @
7f066bb3
/*
* 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
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录