History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/jdi/ClassTypeImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/jdi/ClassTypeImpl.java+428−0
@@ -0,0 +1,428 @@
1+/*
2+ * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package com.sun.tools.jdi;
27+
28+import com.sun.jdi.*;
29+
30+import java.util.*;
31+
32+public class ClassTypeImpl extends ReferenceTypeImpl
33+ implements ClassType
34+{
35+ private boolean cachedSuperclass = false;
36+ private ClassType superclass = null;
37+ private int lastLine = -1;
38+ private List<InterfaceType> interfaces = null;
39+
40+ protected ClassTypeImpl(VirtualMachine aVm,long aRef) {
41+ super(aVm, aRef);
42+ }
43+
44+ public ClassType superclass() {
45+ if(!cachedSuperclass) {
46+ ClassTypeImpl sup = null;
47+ try {
48+ sup = JDWP.ClassType.Superclass.
49+ process(vm, this).superclass;
50+ } catch (JDWPException exc) {
51+ throw exc.toJDIException();
52+ }
53+
54+ /*
55+ * If there is a superclass, cache its
56+ * ClassType here. Otherwise,
57+ * leave the cache reference null.
58+ */
59+ if (sup != null) {
60+ superclass = sup;
61+ }
62+ cachedSuperclass = true;
63+ }
64+
65+ return superclass;
66+ }
67+
68+ public List<InterfaceType> interfaces() {
69+ if (interfaces == null) {
70+ interfaces = getInterfaces();
71+ }
72+ return interfaces;
73+ }
74+
75+ void addInterfaces(List<InterfaceType> list) {
76+ List<InterfaceType> immediate = interfaces();
77+ list.addAll(interfaces());
78+
79+ Iterator iter = immediate.iterator();
80+ while (iter.hasNext()) {
81+ InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next();
82+ interfaze.addSuperinterfaces(list);
83+ }
84+
85+ ClassTypeImpl superclass = (ClassTypeImpl)superclass();
86+ if (superclass != null) {
87+ superclass.addInterfaces(list);
88+ }
89+ }
90+
91+ public List<InterfaceType> allInterfaces() {
92+ List<InterfaceType> all = new ArrayList<InterfaceType>();
93+ addInterfaces(all);
94+ return all;
95+ }
96+
97+ public List<ClassType> subclasses() {
98+ List<ClassType> subs = new ArrayList<ClassType>();
99+ for (ReferenceType refType : vm.allClasses()) {
100+ if (refType instanceof ClassType) {
101+ ClassType clazz = (ClassType)refType;
102+ ClassType superclass = clazz.superclass();
103+ if ((superclass != null) && superclass.equals(this)) {
104+ subs.add((ClassType)refType);
105+ }
106+ }
107+ }
108+
109+ return subs;
110+ }
111+
112+ public boolean isEnum() {
113+ ClassType superclass = superclass();
114+ if (superclass != null &&
115+ superclass.name().equals("java.lang.Enum")) {
116+ return true;
117+ }
118+ return false;
119+ }
120+
121+ public void setValue(Field field, Value value)
122+ throws InvalidTypeException, ClassNotLoadedException {
123+
124+ validateMirror(field);
125+ validateMirrorOrNull(value);
126+ validateFieldSet(field);
127+
128+ // More validation specific to setting from a ClassType
129+ if(!field.isStatic()) {
130+ throw new IllegalArgumentException(
131+ "Must set non-static field through an instance");
132+ }
133+
134+ try {
135+ JDWP.ClassType.SetValues.FieldValue[] values =
136+ new JDWP.ClassType.SetValues.FieldValue[1];
137+ values[0] = new JDWP.ClassType.SetValues.FieldValue(
138+ ((FieldImpl)field).ref(),
139+ // validate and convert if necessary
140+ ValueImpl.prepareForAssignment(value, (FieldImpl)field));
141+
142+ try {
143+ JDWP.ClassType.SetValues.process(vm, this, values);
144+ } catch (JDWPException exc) {
145+ throw exc.toJDIException();
146+ }
147+ } catch (ClassNotLoadedException e) {
148+ /*
149+ * Since we got this exception,
150+ * the field type must be a reference type. The value
151+ * we're trying to set is null, but if the field's
152+ * class has not yet been loaded through the enclosing
153+ * class loader, then setting to null is essentially a
154+ * no-op, and we should allow it without an exception.
155+ */
156+ if (value != null) {
157+ throw e;
158+ }
159+ }
160+ }
161+
162+ PacketStream sendInvokeCommand(final ThreadReferenceImpl thread,
163+ final MethodImpl method,
164+ final ValueImpl[] args,
165+ final int options) {
166+ CommandSender sender =
167+ new CommandSender() {
168+ public PacketStream send() {
169+ return JDWP.ClassType.InvokeMethod.enqueueCommand(
170+ vm, ClassTypeImpl.this, thread,
171+ method.ref(), args, options);
172+ }
173+ };
174+
175+ PacketStream stream;
176+ if ((options & INVOKE_SINGLE_THREADED) != 0) {
177+ stream = thread.sendResumingCommand(sender);
178+ } else {
179+ stream = vm.sendResumingCommand(sender);
180+ }
181+ return stream;
182+ }
183+
184+ PacketStream sendNewInstanceCommand(final ThreadReferenceImpl thread,
185+ final MethodImpl method,
186+ final ValueImpl[] args,
187+ final int options) {
188+ CommandSender sender =
189+ new CommandSender() {
190+ public PacketStream send() {
191+ return JDWP.ClassType.NewInstance.enqueueCommand(
192+ vm, ClassTypeImpl.this, thread,
193+ method.ref(), args, options);
194+ }
195+ };
196+
197+ PacketStream stream;
198+ if ((options & INVOKE_SINGLE_THREADED) != 0) {
199+ stream = thread.sendResumingCommand(sender);
200+ } else {
201+ stream = vm.sendResumingCommand(sender);
202+ }
203+ return stream;
204+ }
205+
206+ public Value invokeMethod(ThreadReference threadIntf, Method methodIntf,
207+ List<? extends Value> origArguments, int options)
208+ throws InvalidTypeException,
209+ ClassNotLoadedException,
210+ IncompatibleThreadStateException,
211+ InvocationException {
212+ validateMirror(threadIntf);
213+ validateMirror(methodIntf);
214+ validateMirrorsOrNulls(origArguments);
215+
216+ MethodImpl method = (MethodImpl)methodIntf;
217+ ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf;
218+
219+ validateMethodInvocation(method);
220+
221+ List<? extends Value> arguments = method.validateAndPrepareArgumentsForInvoke(origArguments);
222+
223+ ValueImpl[] args = arguments.toArray(new ValueImpl[0]);
224+ JDWP.ClassType.InvokeMethod ret;
225+ try {
226+ PacketStream stream =
227+ sendInvokeCommand(thread, method, args, options);
228+ ret = JDWP.ClassType.InvokeMethod.waitForReply(vm, stream);
229+ } catch (JDWPException exc) {
230+ if (exc.errorCode() == JDWP.Error.INVALID_THREAD) {
231+ throw new IncompatibleThreadStateException();
232+ } else {
233+ throw exc.toJDIException();
234+ }
235+ }
236+
237+ /*
238+ * There is an implict VM-wide suspend at the conclusion
239+ * of a normal (non-single-threaded) method invoke
240+ */
241+ if ((options & INVOKE_SINGLE_THREADED) == 0) {
242+ vm.notifySuspend();
243+ }
244+
245+ if (ret.exception != null) {
246+ throw new InvocationException(ret.exception);
247+ } else {
248+ return ret.returnValue;
249+ }
250+ }
251+
252+ public ObjectReference newInstance(ThreadReference threadIntf,
253+ Method methodIntf,
254+ List<? extends Value> origArguments,
255+ int options)
256+ throws InvalidTypeException,
257+ ClassNotLoadedException,
258+ IncompatibleThreadStateException,
259+ InvocationException {
260+ validateMirror(threadIntf);
261+ validateMirror(methodIntf);
262+ validateMirrorsOrNulls(origArguments);
263+
264+ MethodImpl method = (MethodImpl)methodIntf;
265+ ThreadReferenceImpl thread = (ThreadReferenceImpl)threadIntf;
266+
267+ validateConstructorInvocation(method);
268+
269+ List<Value> arguments = method.validateAndPrepareArgumentsForInvoke(
270+ origArguments);
271+ ValueImpl[] args = arguments.toArray(new ValueImpl[0]);
272+ JDWP.ClassType.NewInstance ret = null;
273+ try {
274+ PacketStream stream =
275+ sendNewInstanceCommand(thread, method, args, options);
276+ ret = JDWP.ClassType.NewInstance.waitForReply(vm, stream);
277+ } catch (JDWPException exc) {
278+ if (exc.errorCode() == JDWP.Error.INVALID_THREAD) {
279+ throw new IncompatibleThreadStateException();
280+ } else {
281+ throw exc.toJDIException();
282+ }
283+ }
284+
285+ /*
286+ * There is an implict VM-wide suspend at the conclusion
287+ * of a normal (non-single-threaded) method invoke
288+ */
289+ if ((options & INVOKE_SINGLE_THREADED) == 0) {
290+ vm.notifySuspend();
291+ }
292+
293+ if (ret.exception != null) {
294+ throw new InvocationException(ret.exception);
295+ } else {
296+ return ret.newObject;
297+ }
298+ }
299+
300+ public Method concreteMethodByName(String name, String signature) {
301+ Method method = null;
302+ for (Method candidate : visibleMethods()) {
303+ if (candidate.name().equals(name) &&
304+ candidate.signature().equals(signature) &&
305+ !candidate.isAbstract()) {
306+
307+ method = candidate;
308+ break;
309+ }
310+ }
311+ return method;
312+ }
313+
314+ public List<Method> allMethods() {
315+ ArrayList<Method> list = new ArrayList<Method>(methods());
316+
317+ ClassType clazz = superclass();
318+ while (clazz != null) {
319+ list.addAll(clazz.methods());
320+ clazz = clazz.superclass();
321+ }
322+
323+ /*
324+ * Avoid duplicate checking on each method by iterating through
325+ * duplicate-free allInterfaces() rather than recursing
326+ */
327+ for (InterfaceType interfaze : allInterfaces()) {
328+ list.addAll(interfaze.methods());
329+ }
330+
331+ return list;
332+ }
333+
334+ List<ReferenceType> inheritedTypes() {
335+ List<ReferenceType> inherited = new ArrayList<ReferenceType>();
336+ if (superclass() != null) {
337+ inherited.add(0, (ReferenceType)superclass()); /* insert at front */
338+ }
339+ for (ReferenceType rt : interfaces()) {
340+ inherited.add(rt);
341+ }
342+ return inherited;
343+ }
344+
345+ void validateMethodInvocation(Method method)
346+ throws InvalidTypeException,
347+ InvocationException {
348+ /*
349+ * Method must be in this class or a superclass.
350+ */
351+ ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType();
352+ if (!declType.isAssignableFrom(this)) {
353+ throw new IllegalArgumentException("Invalid method");
354+ }
355+
356+ /*
357+ * Method must be a static and not a static initializer
358+ */
359+ if (!method.isStatic()) {
360+ throw new IllegalArgumentException("Cannot invoke instance method on a class type");
361+ } else if (method.isStaticInitializer()) {
362+ throw new IllegalArgumentException("Cannot invoke static initializer");
363+ }
364+ }
365+
366+ void validateConstructorInvocation(Method method)
367+ throws InvalidTypeException,
368+ InvocationException {
369+ /*
370+ * Method must be in this class.
371+ */
372+ ReferenceTypeImpl declType = (ReferenceTypeImpl)method.declaringType();
373+ if (!declType.equals(this)) {
374+ throw new IllegalArgumentException("Invalid constructor");
375+ }
376+
377+ /*
378+ * Method must be a constructor
379+ */
380+ if (!method.isConstructor()) {
381+ throw new IllegalArgumentException("Cannot create instance with non-constructor");
382+ }
383+ }
384+
385+ void addVisibleMethods(Map<String, Method> methodMap) {
386+ /*
387+ * Add methods from
388+ * parent types first, so that the methods in this class will
389+ * overwrite them in the hash table
390+ */
391+
392+ Iterator iter = interfaces().iterator();
393+ while (iter.hasNext()) {
394+ InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next();
395+ interfaze.addVisibleMethods(methodMap);
396+ }
397+
398+ ClassTypeImpl clazz = (ClassTypeImpl)superclass();
399+ if (clazz != null) {
400+ clazz.addVisibleMethods(methodMap);
401+ }
402+
403+ addToMethodMap(methodMap, methods());
404+ }
405+
406+ boolean isAssignableTo(ReferenceType type) {
407+ ClassTypeImpl superclazz = (ClassTypeImpl)superclass();
408+ if (this.equals(type)) {
409+ return true;
410+ } else if ((superclazz != null) && superclazz.isAssignableTo(type)) {
411+ return true;
412+ } else {
413+ List<InterfaceType> interfaces = interfaces();
414+ Iterator iter = interfaces.iterator();
415+ while (iter.hasNext()) {
416+ InterfaceTypeImpl interfaze = (InterfaceTypeImpl)iter.next();
417+ if (interfaze.isAssignableTo(type)) {
418+ return true;
419+ }
420+ }
421+ return false;
422+ }
423+ }
424+
425+ public String toString() {
426+ return "class " + name() + " (" + loaderString() + ")";
427+ }
428+}