Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java @ 18665:96861e3f8cc5
made CFGPrinterObserver reset (upon close) properly
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 11 Dec 2014 22:14:30 +0100 |
parents | 5a98bf7d847b |
children |
rev | line source |
---|---|
0 | 1 /* |
5998
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
3939
diff
changeset
|
2 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 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. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.jdi; | |
26 | |
27 import com.sun.jdi.*; | |
28 import com.sun.jdi.event.EventQueue; | |
29 import com.sun.jdi.request.EventRequestManager; | |
30 | |
31 import sun.jvm.hotspot.HotSpotAgent; | |
32 import sun.jvm.hotspot.types.TypeDataBase; | |
33 import sun.jvm.hotspot.oops.Klass; | |
34 import sun.jvm.hotspot.oops.InstanceKlass; | |
35 import sun.jvm.hotspot.oops.ArrayKlass; | |
36 import sun.jvm.hotspot.oops.ObjArrayKlass; | |
37 import sun.jvm.hotspot.oops.TypeArrayKlass; | |
38 import sun.jvm.hotspot.oops.Oop; | |
39 import sun.jvm.hotspot.oops.Instance; | |
40 import sun.jvm.hotspot.oops.Array; | |
41 import sun.jvm.hotspot.oops.ObjArray; | |
42 import sun.jvm.hotspot.oops.TypeArray; | |
43 import sun.jvm.hotspot.oops.Symbol; | |
44 import sun.jvm.hotspot.oops.ObjectHeap; | |
45 import sun.jvm.hotspot.oops.DefaultHeapVisitor; | |
46 import sun.jvm.hotspot.oops.JVMDIClassStatus; | |
47 import sun.jvm.hotspot.runtime.VM; | |
48 import sun.jvm.hotspot.runtime.JavaThread; | |
49 import sun.jvm.hotspot.memory.SystemDictionary; | |
50 import sun.jvm.hotspot.memory.SymbolTable; | |
51 import sun.jvm.hotspot.memory.Universe; | |
52 import sun.jvm.hotspot.utilities.Assert; | |
53 | |
54 import java.util.List; | |
55 import java.util.ArrayList; | |
56 import java.util.Map; | |
57 import java.util.Iterator; | |
58 import java.util.Collections; | |
59 import java.util.HashMap; | |
60 import java.util.Observer; | |
61 import java.util.StringTokenizer; | |
62 import java.lang.ref.SoftReference; | |
63 import java.lang.ref.ReferenceQueue; | |
64 import java.lang.ref.Reference; | |
65 | |
66 public class VirtualMachineImpl extends MirrorImpl implements PathSearchingVirtualMachine { | |
67 | |
68 private HotSpotAgent saAgent = new HotSpotAgent(); | |
69 private VM saVM; | |
70 private Universe saUniverse; | |
71 private SystemDictionary saSystemDictionary; | |
72 private SymbolTable saSymbolTable; | |
73 private ObjectHeap saObjectHeap; | |
74 | |
75 VM saVM() { | |
76 return saVM; | |
77 } | |
78 | |
79 SystemDictionary saSystemDictionary() { | |
80 return saSystemDictionary; | |
81 } | |
82 | |
83 SymbolTable saSymbolTable() { | |
84 return saSymbolTable; | |
85 } | |
86 | |
87 Universe saUniverse() { | |
88 return saUniverse; | |
89 } | |
90 | |
91 ObjectHeap saObjectHeap() { | |
92 return saObjectHeap; | |
93 } | |
94 | |
95 com.sun.jdi.VirtualMachineManager vmmgr; | |
96 | |
97 private final ThreadGroup threadGroupForJDI; | |
98 | |
99 // Per-vm singletons for primitive types and for void. | |
100 // singleton-ness protected by "synchronized(this)". | |
101 private BooleanType theBooleanType; | |
102 private ByteType theByteType; | |
103 private CharType theCharType; | |
104 private ShortType theShortType; | |
105 private IntegerType theIntegerType; | |
106 private LongType theLongType; | |
107 private FloatType theFloatType; | |
108 private DoubleType theDoubleType; | |
109 | |
110 private VoidType theVoidType; | |
111 | |
112 private VoidValue voidVal; | |
113 private Map typesByID; // Map<Klass, ReferenceTypeImpl> | |
114 private List typesBySignature; // List<ReferenceTypeImpl> - used in signature search | |
115 private boolean retrievedAllTypes = false; | |
116 private List bootstrapClasses; // all bootstrap classes | |
117 private ArrayList allThreads; | |
118 private ArrayList topLevelGroups; | |
119 final int sequenceNumber; | |
120 | |
121 // ObjectReference cache | |
122 // "objectsByID" protected by "synchronized(this)". | |
123 private final Map objectsByID = new HashMap(); | |
124 private final ReferenceQueue referenceQueue = new ReferenceQueue(); | |
125 | |
126 // names of some well-known classes to jdi | |
127 private Symbol javaLangString; | |
128 private Symbol javaLangThread; | |
129 private Symbol javaLangThreadGroup; | |
130 private Symbol javaLangClass; | |
131 private Symbol javaLangClassLoader; | |
132 | |
133 // used in ReferenceTypeImpl.isThrowableBacktraceField | |
134 private Symbol javaLangThrowable; | |
135 | |
136 // names of classes used in array assignment check | |
137 // refer to ArrayTypeImpl.isAssignableTo | |
138 private Symbol javaLangObject; | |
139 private Symbol javaLangCloneable; | |
140 private Symbol javaIoSerializable; | |
141 | |
142 // symbol used in ClassTypeImpl.isEnum check | |
143 private Symbol javaLangEnum; | |
144 | |
145 Symbol javaLangObject() { | |
146 return javaLangObject; | |
147 } | |
148 | |
149 Symbol javaLangCloneable() { | |
150 return javaLangCloneable; | |
151 } | |
152 | |
153 Symbol javaIoSerializable() { | |
154 return javaIoSerializable; | |
155 } | |
156 | |
157 Symbol javaLangEnum() { | |
158 return javaLangEnum; | |
159 } | |
160 | |
161 Symbol javaLangThrowable() { | |
162 return javaLangThrowable; | |
163 } | |
164 | |
165 // name of the current default stratum | |
166 private String defaultStratum; | |
167 | |
168 // initialize known class name symbols | |
169 private void initClassNameSymbols() { | |
170 SymbolTable st = saSymbolTable(); | |
171 javaLangString = st.probe("java/lang/String"); | |
172 javaLangThread = st.probe("java/lang/Thread"); | |
173 javaLangThreadGroup = st.probe("java/lang/ThreadGroup"); | |
174 javaLangClass = st.probe("java/lang/Class"); | |
175 javaLangClassLoader = st.probe("java/lang/ClassLoader"); | |
176 javaLangThrowable = st.probe("java/lang/Throwable"); | |
177 javaLangObject = st.probe("java/lang/Object"); | |
178 javaLangCloneable = st.probe("java/lang/Cloneable"); | |
179 javaIoSerializable = st.probe("java/io/Serializable"); | |
180 javaLangEnum = st.probe("java/lang/Enum"); | |
181 } | |
182 | |
183 private void init() { | |
184 saVM = VM.getVM(); | |
185 saUniverse = saVM.getUniverse(); | |
186 saSystemDictionary = saVM.getSystemDictionary(); | |
187 saSymbolTable = saVM.getSymbolTable(); | |
188 saObjectHeap = saVM.getObjectHeap(); | |
189 initClassNameSymbols(); | |
190 } | |
191 | |
192 static public VirtualMachineImpl createVirtualMachineForCorefile(VirtualMachineManager mgr, | |
193 String javaExecutableName, | |
194 String coreFileName, | |
195 int sequenceNumber) | |
196 throws Exception { | |
197 if (Assert.ASSERTS_ENABLED) { | |
198 Assert.that(coreFileName != null, "SA VirtualMachineImpl: core filename = null is not yet implemented"); | |
199 } | |
200 if (Assert.ASSERTS_ENABLED) { | |
201 Assert.that(javaExecutableName != null, "SA VirtualMachineImpl: java executable = null is not yet implemented"); | |
202 } | |
203 | |
204 VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber); | |
205 try { | |
206 myvm.saAgent.attach(javaExecutableName, coreFileName); | |
207 myvm.init(); | |
208 } catch (Exception ee) { | |
209 myvm.saAgent.detach(); | |
210 throw ee; | |
211 } | |
212 return myvm; | |
213 } | |
214 | |
215 static public VirtualMachineImpl createVirtualMachineForPID(VirtualMachineManager mgr, | |
216 int pid, | |
217 int sequenceNumber) | |
218 throws Exception { | |
219 | |
220 VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber); | |
221 try { | |
222 myvm.saAgent.attach(pid); | |
223 myvm.init(); | |
224 } catch (Exception ee) { | |
225 myvm.saAgent.detach(); | |
226 throw ee; | |
227 } | |
228 return myvm; | |
229 } | |
230 | |
231 static public VirtualMachineImpl createVirtualMachineForServer(VirtualMachineManager mgr, | |
232 String server, | |
233 int sequenceNumber) | |
234 throws Exception { | |
235 if (Assert.ASSERTS_ENABLED) { | |
236 Assert.that(server != null, "SA VirtualMachineImpl: DebugServer = null is not yet implemented"); | |
237 } | |
238 | |
239 VirtualMachineImpl myvm = new VirtualMachineImpl(mgr, sequenceNumber); | |
240 try { | |
241 myvm.saAgent.attach(server); | |
242 myvm.init(); | |
243 } catch (Exception ee) { | |
244 myvm.saAgent.detach(); | |
245 throw ee; | |
246 } | |
247 return myvm; | |
248 } | |
249 | |
250 | |
251 VirtualMachineImpl(VirtualMachineManager mgr, int sequenceNumber) | |
252 throws Exception { | |
253 super(null); // Can't use super(this) | |
254 vm = this; | |
255 | |
256 this.sequenceNumber = sequenceNumber; | |
257 this.vmmgr = mgr; | |
258 | |
259 /* Create ThreadGroup to be used by all threads servicing | |
260 * this VM. | |
261 */ | |
262 threadGroupForJDI = new ThreadGroup("JDI [" + | |
263 this.hashCode() + "]"); | |
264 | |
265 ((com.sun.tools.jdi.VirtualMachineManagerImpl)mgr).addVirtualMachine(this); | |
6782 | 266 |
267 // By default SA agent classes prefer Windows process debugger | |
268 // to windbg debugger. SA expects special properties to be set | |
269 // to choose other debuggers. We will set those here before | |
270 // attaching to SA agent. | |
271 | |
272 System.setProperty("sun.jvm.hotspot.debugger.useWindbgDebugger", "true"); | |
0 | 273 } |
274 | |
275 // we reflectively use newly spec'ed class because our ALT_BOOTDIR | |
276 // is 1.4.2 and not 1.5. | |
277 private static Class vmCannotBeModifiedExceptionClass = null; | |
278 void throwNotReadOnlyException(String operation) { | |
279 RuntimeException re = null; | |
280 if (vmCannotBeModifiedExceptionClass == null) { | |
281 try { | |
282 vmCannotBeModifiedExceptionClass = Class.forName("com.sun.jdi.VMCannotBeModifiedException"); | |
283 } catch (ClassNotFoundException cnfe) { | |
284 vmCannotBeModifiedExceptionClass = UnsupportedOperationException.class; | |
285 } | |
286 } | |
287 try { | |
288 re = (RuntimeException) vmCannotBeModifiedExceptionClass.newInstance(); | |
289 } catch (Exception exp) { | |
290 re = new RuntimeException(exp.getMessage()); | |
291 } | |
292 throw re; | |
293 } | |
294 | |
295 public boolean equals(Object obj) { | |
296 // Oh boy; big recursion troubles if we don't have this! | |
297 // See MirrorImpl.equals | |
298 return this == obj; | |
299 } | |
300 | |
301 public int hashCode() { | |
302 // big recursion if we don't have this. See MirrorImpl.hashCode | |
303 return System.identityHashCode(this); | |
304 } | |
305 | |
306 public List classesByName(String className) { | |
307 String signature = JNITypeParser.typeNameToSignature(className); | |
308 List list; | |
309 if (!retrievedAllTypes) { | |
310 retrieveAllClasses(); | |
311 } | |
312 list = findReferenceTypes(signature); | |
313 return Collections.unmodifiableList(list); | |
314 } | |
315 | |
316 public List allClasses() { | |
317 if (!retrievedAllTypes) { | |
318 retrieveAllClasses(); | |
319 } | |
320 ArrayList a; | |
321 synchronized (this) { | |
322 a = new ArrayList(typesBySignature); | |
323 } | |
324 return Collections.unmodifiableList(a); | |
325 } | |
326 | |
327 // classes loaded by bootstrap loader | |
328 List bootstrapClasses() { | |
329 if (bootstrapClasses == null) { | |
330 bootstrapClasses = new ArrayList(); | |
331 List all = allClasses(); | |
332 for (Iterator itr = all.iterator(); itr.hasNext();) { | |
333 ReferenceType type = (ReferenceType) itr.next(); | |
334 if (type.classLoader() == null) { | |
335 bootstrapClasses.add(type); | |
336 } | |
337 } | |
338 } | |
339 return bootstrapClasses; | |
340 } | |
341 | |
342 private synchronized List findReferenceTypes(String signature) { | |
343 if (typesByID == null) { | |
344 return new ArrayList(0); | |
345 } | |
346 | |
347 // we haven't sorted types by signatures. But we can take | |
348 // advantage of comparing symbols instead of name. In the worst | |
349 // case, we will be comparing N addresses rather than N strings | |
350 // where N being total no. of classes in allClasses() list. | |
351 | |
352 // The signature could be Lx/y/z; or [.... | |
353 // If it is Lx/y/z; the internal type name is x/y/x | |
354 // for array klasses internal type name is same as | |
355 // signature | |
356 String typeName = null; | |
357 if (signature.charAt(0) == 'L') { | |
358 typeName = signature.substring(1, signature.length() - 1); | |
359 } else { | |
360 typeName = signature; | |
361 } | |
362 | |
363 Symbol typeNameSym = saSymbolTable().probe(typeName); | |
364 // if there is no symbol in VM, then we wouldn't have that type | |
365 if (typeNameSym == null) { | |
366 return new ArrayList(0); | |
367 } | |
368 | |
369 Iterator iter = typesBySignature.iterator(); | |
370 List list = new ArrayList(); | |
371 while (iter.hasNext()) { | |
372 // We have cached type name as symbol in reference type | |
373 ReferenceTypeImpl type = (ReferenceTypeImpl)iter.next(); | |
374 if (typeNameSym.equals(type.typeNameAsSymbol())) { | |
375 list.add(type); | |
376 } | |
377 } | |
378 return list; | |
379 } | |
380 | |
381 private void retrieveAllClasses() { | |
382 final List saKlasses = new ArrayList(); | |
383 SystemDictionary.ClassVisitor visitor = new SystemDictionary.ClassVisitor() { | |
384 public void visit(Klass k) { | |
385 for (Klass l = k; l != null; l = l.arrayKlassOrNull()) { | |
386 // for non-array classes filter out un-prepared classes | |
387 // refer to 'allClasses' in share/back/VirtualMachineImpl.c | |
388 if (l instanceof ArrayKlass) { | |
389 saKlasses.add(l); | |
390 } else { | |
391 int status = l.getClassStatus(); | |
392 if ((status & JVMDIClassStatus.PREPARED) != 0) { | |
393 saKlasses.add(l); | |
394 } | |
395 } | |
396 } | |
397 } | |
398 }; | |
399 | |
400 // refer to jvmtiGetLoadedClasses.cpp - getLoadedClasses in VM code. | |
401 | |
402 // classes from SystemDictionary | |
403 saSystemDictionary.classesDo(visitor); | |
404 | |
405 // From SystemDictionary we do not get primitive single | |
406 // dimensional array classes. add primitive single dimensional array | |
407 // klasses from Universe. | |
408 saVM.getUniverse().basicTypeClassesDo(visitor); | |
409 | |
410 // Hold lock during processing to improve performance | |
411 // and to have safe check/set of retrievedAllTypes | |
412 synchronized (this) { | |
413 if (!retrievedAllTypes) { | |
414 // Number of classes | |
415 int count = saKlasses.size(); | |
416 for (int ii = 0; ii < count; ii++) { | |
417 Klass kk = (Klass)saKlasses.get(ii); | |
418 ReferenceTypeImpl type = referenceType(kk); | |
419 } | |
420 retrievedAllTypes = true; | |
421 } | |
422 } | |
423 } | |
424 | |
425 ReferenceTypeImpl referenceType(Klass kk) { | |
426 ReferenceTypeImpl retType = null; | |
427 synchronized (this) { | |
428 if (typesByID != null) { | |
429 retType = (ReferenceTypeImpl)typesByID.get(kk); | |
430 } | |
431 if (retType == null) { | |
432 retType = addReferenceType(kk); | |
433 } | |
434 } | |
435 return retType; | |
436 } | |
437 | |
438 private void initReferenceTypes() { | |
439 typesByID = new HashMap(); | |
440 typesBySignature = new ArrayList(); | |
441 } | |
442 | |
443 private synchronized ReferenceTypeImpl addReferenceType(Klass kk) { | |
444 if (typesByID == null) { | |
445 initReferenceTypes(); | |
446 } | |
447 ReferenceTypeImpl newRefType = null; | |
448 if (kk instanceof ObjArrayKlass || kk instanceof TypeArrayKlass) { | |
449 newRefType = new ArrayTypeImpl(this, (ArrayKlass)kk); | |
450 } else if (kk instanceof InstanceKlass) { | |
451 if (kk.isInterface()) { | |
452 newRefType = new InterfaceTypeImpl(this, (InstanceKlass)kk); | |
453 } else { | |
454 newRefType = new ClassTypeImpl(this, (InstanceKlass)kk); | |
455 } | |
456 } else { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
5998
diff
changeset
|
457 throw new RuntimeException("should not reach here:" + kk); |
0 | 458 } |
459 | |
460 typesByID.put(kk, newRefType); | |
461 typesBySignature.add(newRefType); | |
462 return newRefType; | |
463 } | |
464 | |
465 ThreadGroup threadGroupForJDI() { | |
466 return threadGroupForJDI; | |
467 } | |
468 | |
469 public void redefineClasses(Map classToBytes) { | |
470 throwNotReadOnlyException("VirtualMachineImpl.redefineClasses()"); | |
471 } | |
472 | |
473 private List getAllThreads() { | |
474 if (allThreads == null) { | |
475 allThreads = new ArrayList(10); // Might be enough, might not be | |
476 for (sun.jvm.hotspot.runtime.JavaThread thread = | |
477 saVM.getThreads().first(); thread != null; | |
478 thread = thread.next()) { | |
479 // refer to JvmtiEnv::GetAllThreads in jvmtiEnv.cpp. | |
480 // filter out the hidden-from-external-view threads. | |
481 if (thread.isHiddenFromExternalView() == false) { | |
482 ThreadReferenceImpl myThread = threadMirror(thread); | |
483 allThreads.add(myThread); | |
484 } | |
485 } | |
486 } | |
487 return allThreads; | |
488 } | |
489 | |
490 public List allThreads() { //fixme jjh | |
491 return Collections.unmodifiableList(getAllThreads()); | |
492 } | |
493 | |
494 public void suspend() { | |
495 throwNotReadOnlyException("VirtualMachineImpl.suspend()"); | |
496 } | |
497 | |
498 public void resume() { | |
499 throwNotReadOnlyException("VirtualMachineImpl.resume()"); | |
500 } | |
501 | |
502 public List topLevelThreadGroups() { //fixme jjh | |
503 // The doc for ThreadGroup says that The top-level thread group | |
504 // is the only thread group whose parent is null. This means there is | |
505 // only one top level thread group. There will be a thread in this | |
506 // group so we will just find a thread whose threadgroup has no parent | |
507 // and that will be it. | |
508 | |
509 if (topLevelGroups == null) { | |
510 topLevelGroups = new ArrayList(1); | |
511 Iterator myIt = getAllThreads().iterator(); | |
512 while (myIt.hasNext()) { | |
513 ThreadReferenceImpl myThread = (ThreadReferenceImpl)myIt.next(); | |
514 ThreadGroupReference myGroup = myThread.threadGroup(); | |
515 ThreadGroupReference myParent = myGroup.parent(); | |
516 if (myGroup.parent() == null) { | |
517 topLevelGroups.add(myGroup); | |
518 break; | |
519 } | |
520 } | |
521 } | |
522 return Collections.unmodifiableList(topLevelGroups); | |
523 } | |
524 | |
525 public EventQueue eventQueue() { | |
526 throwNotReadOnlyException("VirtualMachine.eventQueue()"); | |
527 return null; | |
528 } | |
529 | |
530 public EventRequestManager eventRequestManager() { | |
531 throwNotReadOnlyException("VirtualMachineImpl.eventRequestManager()"); | |
532 return null; | |
533 } | |
534 | |
535 public BooleanValue mirrorOf(boolean value) { | |
536 return new BooleanValueImpl(this,value); | |
537 } | |
538 | |
539 public ByteValue mirrorOf(byte value) { | |
540 return new ByteValueImpl(this,value); | |
541 } | |
542 | |
543 public CharValue mirrorOf(char value) { | |
544 return new CharValueImpl(this,value); | |
545 } | |
546 | |
547 public ShortValue mirrorOf(short value) { | |
548 return new ShortValueImpl(this,value); | |
549 } | |
550 | |
551 public IntegerValue mirrorOf(int value) { | |
552 return new IntegerValueImpl(this,value); | |
553 } | |
554 | |
555 public LongValue mirrorOf(long value) { | |
556 return new LongValueImpl(this,value); | |
557 } | |
558 | |
559 public FloatValue mirrorOf(float value) { | |
560 return new FloatValueImpl(this,value); | |
561 } | |
562 | |
563 public DoubleValue mirrorOf(double value) { | |
564 return new DoubleValueImpl(this,value); | |
565 } | |
566 | |
567 public StringReference mirrorOf(String value) { | |
568 throwNotReadOnlyException("VirtualMachinestop.mirrorOf(String)"); | |
569 return null; | |
570 } | |
571 | |
572 public VoidValue mirrorOfVoid() { | |
573 if (voidVal == null) { | |
574 voidVal = new VoidValueImpl(this); | |
575 } | |
576 return voidVal; | |
577 } | |
578 | |
579 | |
580 public Process process() { | |
581 throwNotReadOnlyException("VirtualMachine.process"); | |
582 return null; | |
583 } | |
584 | |
585 // dispose observer for Class re-use. refer to ConnectorImpl. | |
586 private Observer disposeObserver; | |
587 | |
588 // ConnectorImpl loaded by a different class loader can not access it. | |
589 // i.e., runtime package of <ConnectorImpl, L1> is not the same that of | |
590 // <VirtualMachineImpl, L2> when L1 != L2. So, package private method | |
591 // can be called reflectively after using setAccessible(true). | |
592 | |
593 void setDisposeObserver(Observer observer) { | |
594 disposeObserver = observer; | |
595 } | |
596 | |
597 private void notifyDispose() { | |
598 if (Assert.ASSERTS_ENABLED) { | |
599 Assert.that(disposeObserver != null, "null VM.dispose observer"); | |
600 } | |
601 disposeObserver.update(null, null); | |
602 } | |
603 | |
604 public void dispose() { | |
605 saAgent.detach(); | |
606 notifyDispose(); | |
607 } | |
608 | |
609 public void exit(int exitCode) { | |
610 throwNotReadOnlyException("VirtualMachine.exit(int)"); | |
611 } | |
612 | |
613 public boolean canBeModified() { | |
614 return false; | |
615 } | |
616 | |
617 public boolean canWatchFieldModification() { | |
618 return false; | |
619 } | |
620 | |
621 public boolean canWatchFieldAccess() { | |
622 return false; | |
623 } | |
624 | |
625 public boolean canGetBytecodes() { | |
626 return true; | |
627 } | |
628 | |
629 public boolean canGetSyntheticAttribute() { | |
630 return true; | |
631 } | |
632 | |
633 // FIXME: For now, all monitor capabilities are disabled | |
634 public boolean canGetOwnedMonitorInfo() { | |
635 return false; | |
636 } | |
637 | |
638 public boolean canGetCurrentContendedMonitor() { | |
639 return false; | |
640 } | |
641 | |
642 public boolean canGetMonitorInfo() { | |
643 return false; | |
644 } | |
645 | |
646 // because this SA works only with 1.5 and update releases | |
647 // this should always succeed unlike JVMDI/JDI. | |
648 public boolean canGet1_5LanguageFeatures() { | |
649 return true; | |
650 } | |
651 | |
652 public boolean canUseInstanceFilters() { | |
653 return false; | |
654 } | |
655 | |
656 public boolean canRedefineClasses() { | |
657 return false; | |
658 } | |
659 | |
660 public boolean canAddMethod() { | |
661 return false; | |
662 } | |
663 | |
664 public boolean canUnrestrictedlyRedefineClasses() { | |
665 return false; | |
666 } | |
667 | |
668 public boolean canPopFrames() { | |
669 return false; | |
670 } | |
671 | |
672 public boolean canGetSourceDebugExtension() { | |
673 // We can use InstanceKlass.getSourceDebugExtension only if | |
674 // ClassFileParser parsed the info. But, ClassFileParser parses | |
675 // SourceDebugExtension attribute only if corresponding JVMDI/TI | |
676 // capability is set to true. Currently, vmStructs does not expose | |
677 // JVMDI/TI capabilities and hence we conservatively assume false. | |
678 return false; | |
679 } | |
680 | |
681 public boolean canRequestVMDeathEvent() { | |
682 return false; | |
683 } | |
684 | |
685 // new method since 1.6 | |
686 public boolean canForceEarlyReturn() { | |
687 return false; | |
688 } | |
689 | |
690 // new method since 1.6 | |
691 public boolean canGetConstantPool() { | |
692 return true; | |
693 } | |
694 | |
695 // new method since 1.6 | |
696 public boolean canGetClassFileVersion() { | |
697 return true; | |
698 } | |
699 | |
700 // new method since 1.6. | |
701 public boolean canGetMethodReturnValues() { | |
702 return false; | |
703 } | |
704 | |
705 // new method since 1.6 | |
706 // Real body will be supplied later. | |
707 public boolean canGetInstanceInfo() { | |
708 return true; | |
709 } | |
710 | |
711 // new method since 1.6 | |
712 public boolean canUseSourceNameFilters() { | |
713 return false; | |
714 } | |
715 | |
716 // new method since 1.6. | |
717 public boolean canRequestMonitorEvents() { | |
718 return false; | |
719 } | |
720 | |
721 // new method since 1.6. | |
722 public boolean canGetMonitorFrameInfo() { | |
723 return true; | |
724 } | |
725 | |
726 // new method since 1.6 | |
727 // Real body will be supplied later. | |
728 public long[] instanceCounts(List classes) { | |
729 if (!canGetInstanceInfo()) { | |
730 throw new UnsupportedOperationException( | |
731 "target does not support getting instances"); | |
732 } | |
733 | |
734 final long[] retValue = new long[classes.size()] ; | |
735 | |
736 final Klass [] klassArray = new Klass[classes.size()]; | |
737 | |
738 boolean allAbstractClasses = true; | |
739 for (int i=0; i < classes.size(); i++) { | |
740 ReferenceTypeImpl rti = (ReferenceTypeImpl)classes.get(i); | |
741 klassArray[i] = rti.ref(); | |
742 retValue[i]=0; | |
743 if (!(rti.isAbstract() || ((ReferenceType)rti instanceof InterfaceType))) { | |
744 allAbstractClasses = false; | |
745 } | |
746 } | |
747 | |
748 if (allAbstractClasses) { | |
749 return retValue; | |
750 } | |
751 final int size = classes.size(); | |
752 saObjectHeap.iterate(new DefaultHeapVisitor() { | |
753 public boolean doObj(Oop oop) { | |
754 for (int i=0; i < size; i++) { | |
755 if (klassArray[i].equals(oop.getKlass())) { | |
756 retValue[i]++; | |
757 break; | |
758 } | |
759 } | |
760 return false; | |
761 } | |
762 }); | |
763 | |
764 return retValue; | |
765 } | |
766 | |
767 private List getPath (String pathName) { | |
768 String cp = saVM.getSystemProperty(pathName); | |
769 String pathSep = saVM.getSystemProperty("path.separator"); | |
770 ArrayList al = new ArrayList(); | |
771 StringTokenizer st = new StringTokenizer(cp, pathSep); | |
772 while (st.hasMoreTokens()) { | |
773 al.add(st.nextToken()); | |
774 } | |
775 al.trimToSize(); | |
776 return al; | |
777 } | |
778 | |
779 public List classPath() { | |
780 return getPath("java.class.path"); | |
781 } | |
782 | |
783 public List bootClassPath() { | |
784 return getPath("sun.boot.class.path"); | |
785 } | |
786 | |
787 public String baseDirectory() { | |
788 return saVM.getSystemProperty("user.dir"); | |
789 } | |
790 | |
791 public void setDefaultStratum(String stratum) { | |
792 defaultStratum = stratum; | |
793 } | |
794 | |
795 public String getDefaultStratum() { | |
796 return defaultStratum; | |
797 } | |
798 | |
799 public String description() { | |
800 return java.text.MessageFormat.format(java.util.ResourceBundle. | |
801 getBundle("com.sun.tools.jdi.resources.jdi").getString("version_format"), | |
2471
37be97a58393
7010849: 5/5 Extraneous javac source/target options when building sa-jdi
andrew
parents:
1552
diff
changeset
|
802 "" + vmmgr.majorInterfaceVersion(), |
37be97a58393
7010849: 5/5 Extraneous javac source/target options when building sa-jdi
andrew
parents:
1552
diff
changeset
|
803 "" + vmmgr.minorInterfaceVersion(), |
37be97a58393
7010849: 5/5 Extraneous javac source/target options when building sa-jdi
andrew
parents:
1552
diff
changeset
|
804 name()); |
0 | 805 } |
806 | |
807 public String version() { | |
808 return saVM.getSystemProperty("java.version"); | |
809 } | |
810 | |
811 public String name() { | |
812 StringBuffer sb = new StringBuffer(); | |
813 sb.append("JVM version "); | |
814 sb.append(version()); | |
815 sb.append(" ("); | |
816 sb.append(saVM.getSystemProperty("java.vm.name")); | |
817 sb.append(", "); | |
818 sb.append(saVM.getSystemProperty("java.vm.info")); | |
819 sb.append(")"); | |
820 return sb.toString(); | |
821 } | |
822 | |
823 // from interface Mirror | |
824 public VirtualMachine virtualMachine() { | |
825 return this; | |
826 } | |
827 | |
828 public String toString() { | |
829 return name(); | |
830 } | |
831 | |
832 public void setDebugTraceMode(int traceFlags) { | |
833 // spec. says output is implementation dependent | |
834 // and trace mode may be ignored. we ignore it :-) | |
835 } | |
836 | |
837 // heap walking API | |
838 | |
839 // capability check | |
840 public boolean canWalkHeap() { | |
841 return true; | |
842 } | |
843 | |
844 // return a list of all objects in heap | |
845 public List/*<ObjectReference>*/ allObjects() { | |
846 final List objects = new ArrayList(0); | |
847 saObjectHeap.iterate( | |
848 new DefaultHeapVisitor() { | |
849 public boolean doObj(Oop oop) { | |
850 objects.add(objectMirror(oop)); | |
851 return false; | |
852 } | |
853 }); | |
854 return objects; | |
855 } | |
856 | |
857 // equivalent to objectsByType(type, true) | |
858 public List/*<ObjectReference>*/ objectsByType(ReferenceType type) { | |
859 return objectsByType(type, true); | |
860 } | |
861 | |
862 // returns objects of type exactly equal to given type | |
863 private List/*<ObjectReference>*/ objectsByExactType(ReferenceType type) { | |
864 final List objects = new ArrayList(0); | |
865 final Klass givenKls = ((ReferenceTypeImpl)type).ref(); | |
866 saObjectHeap.iterate(new DefaultHeapVisitor() { | |
867 public boolean doObj(Oop oop) { | |
868 if (givenKls.equals(oop.getKlass())) { | |
869 objects.add(objectMirror(oop)); | |
870 } | |
871 return false; | |
872 } | |
873 }); | |
874 return objects; | |
875 } | |
876 | |
877 // returns objects of given type as well as it's subtypes | |
878 private List/*<ObjectReference>*/ objectsBySubType(ReferenceType type) { | |
879 final List objects = new ArrayList(0); | |
880 final ReferenceType givenType = type; | |
881 saObjectHeap.iterate(new DefaultHeapVisitor() { | |
882 public boolean doObj(Oop oop) { | |
883 ReferenceTypeImpl curType = (ReferenceTypeImpl) referenceType(oop.getKlass()); | |
884 if (curType.isAssignableTo(givenType)) { | |
885 objects.add(objectMirror(oop)); | |
886 } | |
887 return false; | |
888 } | |
889 }); | |
890 return objects; | |
891 } | |
892 | |
893 // includeSubtypes - do you want to include subclass/subtype instances of given | |
894 // ReferenceType or do we want objects of exact type only? | |
895 public List/*<ObjectReference>*/ objectsByType(ReferenceType type, boolean includeSubtypes) { | |
896 Klass kls = ((ReferenceTypeImpl)type).ref(); | |
897 if (kls instanceof InstanceKlass) { | |
898 InstanceKlass ik = (InstanceKlass) kls; | |
5998
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
3939
diff
changeset
|
899 // if the Klass is final or if there are no subklasses loaded yet |
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
3939
diff
changeset
|
900 if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) { |
49036505ab5f
7154670: The instanceKlass _implementors[] and _nof_implementors are not needed for non-interface klass.
jiangli
parents:
3939
diff
changeset
|
901 includeSubtypes = false; |
0 | 902 } |
903 } else { | |
904 // no subtypes for primitive array types | |
905 ArrayTypeImpl arrayType = (ArrayTypeImpl) type; | |
906 try { | |
907 Type componentType = arrayType.componentType(); | |
908 if (componentType instanceof PrimitiveType) { | |
909 includeSubtypes = false; | |
910 } | |
911 } catch (ClassNotLoadedException cnle) { | |
912 // ignore. component type not yet loaded | |
913 } | |
914 } | |
915 | |
916 if (includeSubtypes) { | |
917 return objectsBySubType(type); | |
918 } else { | |
919 return objectsByExactType(type); | |
920 } | |
921 } | |
922 | |
923 Type findBootType(String signature) throws ClassNotLoadedException { | |
924 List types = allClasses(); | |
925 Iterator iter = types.iterator(); | |
926 while (iter.hasNext()) { | |
927 ReferenceType type = (ReferenceType)iter.next(); | |
928 if ((type.classLoader() == null) && | |
929 (type.signature().equals(signature))) { | |
930 return type; | |
931 } | |
932 } | |
933 JNITypeParser parser = new JNITypeParser(signature); | |
934 throw new ClassNotLoadedException(parser.typeName(), | |
935 "Type " + parser.typeName() + " not loaded"); | |
936 } | |
937 | |
938 BooleanType theBooleanType() { | |
939 if (theBooleanType == null) { | |
940 synchronized(this) { | |
941 if (theBooleanType == null) { | |
942 theBooleanType = new BooleanTypeImpl(this); | |
943 } | |
944 } | |
945 } | |
946 return theBooleanType; | |
947 } | |
948 | |
949 ByteType theByteType() { | |
950 if (theByteType == null) { | |
951 synchronized(this) { | |
952 if (theByteType == null) { | |
953 theByteType = new ByteTypeImpl(this); | |
954 } | |
955 } | |
956 } | |
957 return theByteType; | |
958 } | |
959 | |
960 CharType theCharType() { | |
961 if (theCharType == null) { | |
962 synchronized(this) { | |
963 if (theCharType == null) { | |
964 theCharType = new CharTypeImpl(this); | |
965 } | |
966 } | |
967 } | |
968 return theCharType; | |
969 } | |
970 | |
971 ShortType theShortType() { | |
972 if (theShortType == null) { | |
973 synchronized(this) { | |
974 if (theShortType == null) { | |
975 theShortType = new ShortTypeImpl(this); | |
976 } | |
977 } | |
978 } | |
979 return theShortType; | |
980 } | |
981 | |
982 IntegerType theIntegerType() { | |
983 if (theIntegerType == null) { | |
984 synchronized(this) { | |
985 if (theIntegerType == null) { | |
986 theIntegerType = new IntegerTypeImpl(this); | |
987 } | |
988 } | |
989 } | |
990 return theIntegerType; | |
991 } | |
992 | |
993 LongType theLongType() { | |
994 if (theLongType == null) { | |
995 synchronized(this) { | |
996 if (theLongType == null) { | |
997 theLongType = new LongTypeImpl(this); | |
998 } | |
999 } | |
1000 } | |
1001 return theLongType; | |
1002 } | |
1003 | |
1004 FloatType theFloatType() { | |
1005 if (theFloatType == null) { | |
1006 synchronized(this) { | |
1007 if (theFloatType == null) { | |
1008 theFloatType = new FloatTypeImpl(this); | |
1009 } | |
1010 } | |
1011 } | |
1012 return theFloatType; | |
1013 } | |
1014 | |
1015 DoubleType theDoubleType() { | |
1016 if (theDoubleType == null) { | |
1017 synchronized(this) { | |
1018 if (theDoubleType == null) { | |
1019 theDoubleType = new DoubleTypeImpl(this); | |
1020 } | |
1021 } | |
1022 } | |
1023 return theDoubleType; | |
1024 } | |
1025 | |
1026 VoidType theVoidType() { | |
1027 if (theVoidType == null) { | |
1028 synchronized(this) { | |
1029 if (theVoidType == null) { | |
1030 theVoidType = new VoidTypeImpl(this); | |
1031 } | |
1032 } | |
1033 } | |
1034 return theVoidType; | |
1035 } | |
1036 | |
1037 PrimitiveType primitiveTypeMirror(char tag) { | |
1038 switch (tag) { | |
1039 case 'Z': | |
1040 return theBooleanType(); | |
1041 case 'B': | |
1042 return theByteType(); | |
1043 case 'C': | |
1044 return theCharType(); | |
1045 case 'S': | |
1046 return theShortType(); | |
1047 case 'I': | |
1048 return theIntegerType(); | |
1049 case 'J': | |
1050 return theLongType(); | |
1051 case 'F': | |
1052 return theFloatType(); | |
1053 case 'D': | |
1054 return theDoubleType(); | |
1055 default: | |
1056 throw new IllegalArgumentException("Unrecognized primitive tag " + tag); | |
1057 } | |
1058 } | |
1059 | |
1060 private void processQueue() { | |
1061 Reference ref; | |
1062 while ((ref = referenceQueue.poll()) != null) { | |
1063 SoftObjectReference softRef = (SoftObjectReference)ref; | |
1064 removeObjectMirror(softRef); | |
1065 } | |
1066 } | |
1067 | |
1068 // Address value is used as uniqueID by ObjectReferenceImpl | |
1069 long getAddressValue(Oop obj) { | |
1070 return vm.saVM.getDebugger().getAddressValue(obj.getHandle()); | |
1071 } | |
1072 | |
1073 synchronized ObjectReferenceImpl objectMirror(Oop key) { | |
1074 | |
1075 // Handle any queue elements that are not strongly reachable | |
1076 processQueue(); | |
1077 | |
1078 if (key == null) { | |
1079 return null; | |
1080 } | |
1081 ObjectReferenceImpl object = null; | |
1082 | |
1083 /* | |
1084 * Attempt to retrieve an existing object object reference | |
1085 */ | |
1086 SoftObjectReference ref = (SoftObjectReference)objectsByID.get(key); | |
1087 if (ref != null) { | |
1088 object = ref.object(); | |
1089 } | |
1090 | |
1091 /* | |
1092 * If the object wasn't in the table, or it's soft reference was | |
1093 * cleared, create a new instance. | |
1094 */ | |
1095 if (object == null) { | |
1096 if (key instanceof Instance) { | |
1097 // look for well-known classes | |
1098 Symbol className = key.getKlass().getName(); | |
1099 if (Assert.ASSERTS_ENABLED) { | |
1100 Assert.that(className != null, "Null class name"); | |
1101 } | |
1102 Instance inst = (Instance) key; | |
1103 if (className.equals(javaLangString)) { | |
1104 object = new StringReferenceImpl(this, inst); | |
1105 } else if (className.equals(javaLangThread)) { | |
1106 object = new ThreadReferenceImpl(this, inst); | |
1107 } else if (className.equals(javaLangThreadGroup)) { | |
1108 object = new ThreadGroupReferenceImpl(this, inst); | |
1109 } else if (className.equals(javaLangClass)) { | |
1110 object = new ClassObjectReferenceImpl(this, inst); | |
1111 } else if (className.equals(javaLangClassLoader)) { | |
1112 object = new ClassLoaderReferenceImpl(this, inst); | |
1113 } else { | |
1114 // not a well-known class. But the base class may be | |
1115 // one of the known classes. | |
1116 Klass kls = key.getKlass().getSuper(); | |
1117 while (kls != null) { | |
1118 className = kls.getName(); | |
1119 // java.lang.Class and java.lang.String are final classes | |
1120 if (className.equals(javaLangThread)) { | |
1121 object = new ThreadReferenceImpl(this, inst); | |
1122 break; | |
1123 } else if(className.equals(javaLangThreadGroup)) { | |
1124 object = new ThreadGroupReferenceImpl(this, inst); | |
1125 break; | |
1126 } else if (className.equals(javaLangClassLoader)) { | |
1127 object = new ClassLoaderReferenceImpl(this, inst); | |
1128 break; | |
1129 } | |
1130 kls = kls.getSuper(); | |
1131 } | |
1132 | |
1133 if (object == null) { | |
1134 // create generic object reference | |
1135 object = new ObjectReferenceImpl(this, inst); | |
1136 } | |
1137 } | |
1138 } else if (key instanceof TypeArray) { | |
1139 object = new ArrayReferenceImpl(this, (Array) key); | |
1140 } else if (key instanceof ObjArray) { | |
1141 object = new ArrayReferenceImpl(this, (Array) key); | |
1142 } else { | |
1143 throw new RuntimeException("unexpected object type " + key); | |
1144 } | |
1145 ref = new SoftObjectReference(key, object, referenceQueue); | |
1146 | |
1147 /* | |
1148 * If there was no previous entry in the table, we add one here | |
1149 * If the previous entry was cleared, we replace it here. | |
1150 */ | |
1151 objectsByID.put(key, ref); | |
1152 } else { | |
1153 ref.incrementCount(); | |
1154 } | |
1155 | |
1156 return object; | |
1157 } | |
1158 | |
1159 synchronized void removeObjectMirror(SoftObjectReference ref) { | |
1160 /* | |
1161 * This will remove the soft reference if it has not been | |
1162 * replaced in the cache. | |
1163 */ | |
1164 objectsByID.remove(ref.key()); | |
1165 } | |
1166 | |
1167 StringReferenceImpl stringMirror(Instance id) { | |
1168 return (StringReferenceImpl) objectMirror(id); | |
1169 } | |
1170 | |
1171 ArrayReferenceImpl arrayMirror(Array id) { | |
1172 return (ArrayReferenceImpl) objectMirror(id); | |
1173 } | |
1174 | |
1175 ThreadReferenceImpl threadMirror(Instance id) { | |
1176 return (ThreadReferenceImpl) objectMirror(id); | |
1177 } | |
1178 | |
1179 ThreadReferenceImpl threadMirror(JavaThread jt) { | |
1180 return (ThreadReferenceImpl) objectMirror(jt.getThreadObj()); | |
1181 } | |
1182 | |
1183 ThreadGroupReferenceImpl threadGroupMirror(Instance id) { | |
1184 return (ThreadGroupReferenceImpl) objectMirror(id); | |
1185 } | |
1186 | |
1187 ClassLoaderReferenceImpl classLoaderMirror(Instance id) { | |
1188 return (ClassLoaderReferenceImpl) objectMirror(id); | |
1189 } | |
1190 | |
1191 ClassObjectReferenceImpl classObjectMirror(Instance id) { | |
1192 return (ClassObjectReferenceImpl) objectMirror(id); | |
1193 } | |
1194 | |
1195 // Use of soft refs and caching stuff here has to be re-examined. | |
1196 // It might not make sense for JDI - SA. | |
1197 static private class SoftObjectReference extends SoftReference { | |
1198 int count; | |
1199 Object key; | |
1200 | |
1201 SoftObjectReference(Object key, ObjectReferenceImpl mirror, | |
1202 ReferenceQueue queue) { | |
1203 super(mirror, queue); | |
1204 this.count = 1; | |
1205 this.key = key; | |
1206 } | |
1207 | |
1208 int count() { | |
1209 return count; | |
1210 } | |
1211 | |
1212 void incrementCount() { | |
1213 count++; | |
1214 } | |
1215 | |
1216 Object key() { | |
1217 return key; | |
1218 } | |
1219 | |
1220 ObjectReferenceImpl object() { | |
1221 return (ObjectReferenceImpl)get(); | |
1222 } | |
1223 } | |
1224 } |