Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/jdi/ObjectReferenceImpl.java @ 2245:638119ce7cfd
7009309: JSR 292: compiler/6991596/Test6991596.java crashes on fastdebug JDK7/b122
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Tue, 01 Feb 2011 03:38:44 -0800 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
2 * Copyright (c) 2002, 2009, 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:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
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:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.jdi; | |
26 | |
27 import java.io.*; | |
28 import com.sun.jdi.*; | |
29 | |
30 import sun.jvm.hotspot.debugger.Address; | |
31 import sun.jvm.hotspot.debugger.OopHandle; | |
32 import sun.jvm.hotspot.oops.Oop; | |
33 import sun.jvm.hotspot.oops.Mark; | |
34 import sun.jvm.hotspot.oops.Instance; | |
35 import sun.jvm.hotspot.oops.Array; | |
36 import sun.jvm.hotspot.oops.OopUtilities; | |
37 import sun.jvm.hotspot.oops.Klass; | |
38 import sun.jvm.hotspot.oops.DefaultHeapVisitor; | |
39 import sun.jvm.hotspot.runtime.JavaThread; | |
40 import sun.jvm.hotspot.runtime.JavaVFrame; | |
41 import sun.jvm.hotspot.runtime.MonitorInfo; | |
42 import sun.jvm.hotspot.runtime.ObjectMonitor; | |
43 import sun.jvm.hotspot.runtime.Threads; | |
44 import sun.jvm.hotspot.utilities.Assert; | |
45 | |
46 import java.util.*; | |
47 | |
48 public class ObjectReferenceImpl extends ValueImpl implements ObjectReference { | |
49 private Oop saObject; | |
50 private long myID; | |
51 private boolean monitorInfoCached = false; | |
52 private ThreadReferenceImpl owningThread = null; | |
53 private List waitingThreads = null; // List<ThreadReferenceImpl> | |
54 private int entryCount = 0; | |
55 | |
56 private static long nextID = 0L; | |
57 private static synchronized long nextID() { | |
58 return nextID++; | |
59 } | |
60 | |
61 ObjectReferenceImpl(VirtualMachine aVm, sun.jvm.hotspot.oops.Oop oRef) { | |
62 super(aVm); | |
63 saObject = oRef; | |
64 myID = nextID(); | |
65 } | |
66 | |
67 protected Oop ref() { | |
68 return saObject; | |
69 } | |
70 | |
71 public Type type() { | |
72 return referenceType(); | |
73 } | |
74 | |
75 public ReferenceType referenceType() { | |
76 Klass myKlass = ref().getKlass(); | |
77 return vm.referenceType(myKlass); | |
78 } | |
79 | |
80 public Value getValue(Field sig) { | |
81 List list = new ArrayList(1); | |
82 list.add(sig); | |
83 Map map = getValues(list); | |
84 return(Value)map.get(sig); | |
85 } | |
86 | |
87 public Map getValues(List theFields) { | |
88 //validateMirrors(theFields); | |
89 | |
90 List staticFields = new ArrayList(0); | |
91 int size = theFields.size(); | |
92 List instanceFields = new ArrayList(size); | |
93 | |
94 for (int i=0; i<size; i++) { | |
95 sun.jvm.hotspot.jdi.FieldImpl field = | |
96 (sun.jvm.hotspot.jdi.FieldImpl)theFields.get(i); | |
97 | |
98 // Make sure the field is valid | |
99 ((ReferenceTypeImpl)referenceType()).validateFieldAccess(field); | |
100 | |
101 // FIX ME! We need to do some sanity checking | |
102 // here; make sure the field belongs to this | |
103 // object. | |
104 if (field.isStatic()) { | |
105 staticFields.add(field); | |
106 } else { | |
107 instanceFields.add(field); | |
108 } | |
109 } | |
110 | |
111 // Look up static field(s) first to mimic the JDI implementation | |
112 Map map; | |
113 if (staticFields.size() > 0) { | |
114 map = referenceType().getValues(staticFields); | |
115 } else { | |
116 map = new HashMap(size); | |
117 } | |
118 | |
119 // Then get instance field(s) | |
120 size = instanceFields.size(); | |
121 for (int ii=0; ii<size; ii++){ | |
122 FieldImpl fieldImpl = (FieldImpl)instanceFields.get(ii); | |
123 map.put(fieldImpl, fieldImpl.getValue(saObject)); | |
124 } | |
125 | |
126 return map; | |
127 } | |
128 | |
129 public void setValue(Field field, Value value) | |
130 throws InvalidTypeException, ClassNotLoadedException { | |
131 vm.throwNotReadOnlyException("ObjectReference.setValue(...)"); | |
132 } | |
133 | |
134 public Value invokeMethod(ThreadReference threadIntf, Method methodIntf, | |
135 List arguments, int options) | |
136 throws InvalidTypeException, | |
137 IncompatibleThreadStateException, | |
138 InvocationException, | |
139 ClassNotLoadedException { | |
140 vm.throwNotReadOnlyException("ObjectReference.invokeMethod(...)"); | |
141 return null; | |
142 } | |
143 | |
144 public void disableCollection() { | |
145 vm.throwNotReadOnlyException("ObjectReference.disableCollection()"); | |
146 } | |
147 | |
148 public void enableCollection() { | |
149 vm.throwNotReadOnlyException("ObjectReference.enableCollection()"); | |
150 } | |
151 | |
152 public boolean isCollected() { | |
153 vm.throwNotReadOnlyException("ObjectReference.isCollected()"); | |
154 return false; | |
155 } | |
156 | |
157 public long uniqueID() { | |
158 return myID; | |
159 } | |
160 | |
161 public List waitingThreads() throws IncompatibleThreadStateException { | |
162 if (vm.canGetMonitorInfo() == false) { | |
163 throw new UnsupportedOperationException(); | |
164 } | |
165 | |
166 if (! monitorInfoCached) { | |
167 computeMonitorInfo(); | |
168 } | |
169 return waitingThreads; | |
170 } | |
171 | |
172 | |
173 public ThreadReference owningThread() throws IncompatibleThreadStateException { | |
174 if (vm.canGetMonitorInfo() == false) { | |
175 throw new UnsupportedOperationException(); | |
176 } | |
177 | |
178 if (! monitorInfoCached) { | |
179 computeMonitorInfo(); | |
180 } | |
181 return owningThread; | |
182 } | |
183 | |
184 | |
185 public int entryCount() throws IncompatibleThreadStateException { | |
186 if (vm.canGetMonitorInfo() == false) { | |
187 throw new UnsupportedOperationException(); | |
188 } | |
189 | |
190 if (! monitorInfoCached) { | |
191 computeMonitorInfo(); | |
192 } | |
193 return entryCount; | |
194 } | |
195 | |
196 // new method since 1.6. | |
197 // Real body will be supplied later. | |
198 public List referringObjects(long maxReferrers) { | |
199 if (!vm.canGetInstanceInfo()) { | |
200 throw new UnsupportedOperationException( | |
201 "target does not support getting instances"); | |
202 } | |
203 if (maxReferrers < 0) { | |
204 throw new IllegalArgumentException("maxReferrers is less than zero: " | |
205 + maxReferrers); | |
206 } | |
207 final ObjectReference obj = this; | |
208 final List objects = new ArrayList(0); | |
209 final long max = maxReferrers; | |
210 vm.saObjectHeap().iterate(new DefaultHeapVisitor() { | |
211 private long refCount = 0; | |
212 public boolean doObj(Oop oop) { | |
213 try { | |
214 ObjectReference objref = vm.objectMirror(oop); | |
215 List fields = objref.referenceType().allFields(); | |
216 for (int i=0; i < fields.size(); i++) { | |
217 Field fld = (Field)fields.get(i); | |
218 if (objref.getValue(fld).equals(obj) && !objects.contains(objref)) { | |
219 objects.add(objref); | |
220 refCount++; | |
221 } | |
222 } | |
223 if (max > 0 && refCount >= max) { | |
224 return true; | |
225 } | |
226 } catch (RuntimeException x) { | |
227 // Ignore RuntimeException thrown from vm.objectMirror(oop) | |
228 // for bad oop. It is possible to see some bad oop | |
229 // because heap might be iterating at no safepoint. | |
230 } | |
231 return false; | |
232 | |
233 } | |
234 }); | |
235 return objects; | |
236 } | |
237 | |
238 // refer to JvmtiEnvBase::count_locked_objects. | |
239 // Count the number of objects for a lightweight monitor. The obj | |
240 // parameter is object that owns the monitor so this routine will | |
241 // count the number of times the same object was locked by frames | |
242 // in JavaThread. i.e., we count total number of times the same | |
243 // object is (lightweight) locked by given thread. | |
244 private int countLockedObjects(JavaThread jt, Oop obj) { | |
245 int res = 0; | |
246 JavaVFrame frame = jt.getLastJavaVFrameDbg(); | |
247 while (frame != null) { | |
248 List monitors = frame.getMonitors(); | |
249 OopHandle givenHandle = obj.getHandle(); | |
250 for (Iterator itr = monitors.iterator(); itr.hasNext();) { | |
251 MonitorInfo mi = (MonitorInfo) itr.next(); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
0
diff
changeset
|
252 if (mi.eliminated() && frame.isCompiledFrame()) continue; // skip eliminated monitor |
0 | 253 if (givenHandle.equals(mi.owner())) { |
254 res++; | |
255 } | |
256 } | |
257 frame = (JavaVFrame) frame.javaSender(); | |
258 } | |
259 return res; | |
260 } | |
261 | |
262 // wrappers on same named method of Threads class | |
263 // returns List<JavaThread> | |
264 private List getPendingThreads(ObjectMonitor mon) { | |
265 return vm.saVM().getThreads().getPendingThreads(mon); | |
266 } | |
267 | |
268 // returns List<JavaThread> | |
269 private List getWaitingThreads(ObjectMonitor mon) { | |
270 return vm.saVM().getThreads().getWaitingThreads(mon); | |
271 } | |
272 | |
273 private JavaThread owningThreadFromMonitor(Address addr) { | |
274 return vm.saVM().getThreads().owningThreadFromMonitor(addr); | |
275 } | |
276 | |
277 // refer to JvmtiEnv::GetObjectMonitorUsage | |
278 private void computeMonitorInfo() { | |
279 monitorInfoCached = true; | |
280 Mark mark = saObject.getMark(); | |
281 ObjectMonitor mon = null; | |
282 Address owner = null; | |
283 // check for heavyweight monitor | |
284 if (! mark.hasMonitor()) { | |
285 // check for lightweight monitor | |
286 if (mark.hasLocker()) { | |
287 owner = mark.locker().getAddress(); // save the address of the Lock word | |
288 } | |
289 // implied else: no owner | |
290 } else { | |
291 // this object has a heavyweight monitor | |
292 mon = mark.monitor(); | |
293 | |
294 // The owner field of a heavyweight monitor may be NULL for no | |
295 // owner, a JavaThread * or it may still be the address of the | |
296 // Lock word in a JavaThread's stack. A monitor can be inflated | |
297 // by a non-owning JavaThread, but only the owning JavaThread | |
298 // can change the owner field from the Lock word to the | |
299 // JavaThread * and it may not have done that yet. | |
300 owner = mon.owner(); | |
301 } | |
302 | |
303 // find the owning thread | |
304 if (owner != null) { | |
305 owningThread = vm.threadMirror(owningThreadFromMonitor(owner)); | |
306 } | |
307 | |
308 // compute entryCount | |
309 if (owningThread != null) { | |
310 if (owningThread.getJavaThread().getAddress().equals(owner)) { | |
311 // the owner field is the JavaThread * | |
312 if (Assert.ASSERTS_ENABLED) { | |
313 Assert.that(false, "must have heavyweight monitor with JavaThread * owner"); | |
314 } | |
315 entryCount = (int) mark.monitor().recursions() + 1; | |
316 } else { | |
317 // The owner field is the Lock word on the JavaThread's stack | |
318 // so the recursions field is not valid. We have to count the | |
319 // number of recursive monitor entries the hard way. | |
320 entryCount = countLockedObjects(owningThread.getJavaThread(), saObject); | |
321 } | |
322 } | |
323 | |
324 // find the contenders & waiters | |
325 waitingThreads = new ArrayList(); | |
326 if (mon != null) { | |
327 // this object has a heavyweight monitor. threads could | |
328 // be contenders or waiters | |
329 // add all contenders | |
330 List pendingThreads = getPendingThreads(mon); | |
331 // convert the JavaThreads to ThreadReferenceImpls | |
332 for (Iterator itrPend = pendingThreads.iterator(); itrPend.hasNext();) { | |
333 waitingThreads.add(vm.threadMirror((JavaThread) itrPend.next())); | |
334 } | |
335 | |
336 // add all waiters (threads in Object.wait()) | |
337 // note that we don't do this JVMTI way. To do it JVMTI way, | |
338 // we would need to access ObjectWaiter list maintained in | |
339 // ObjectMonitor::_queue. But we don't have this struct exposed | |
340 // in vmStructs. We do waiters list in a way similar to getting | |
341 // pending threads list | |
342 List objWaitingThreads = getWaitingThreads(mon); | |
343 // convert the JavaThreads to ThreadReferenceImpls | |
344 for (Iterator itrWait = objWaitingThreads.iterator(); itrWait.hasNext();) { | |
345 waitingThreads.add(vm.threadMirror((JavaThread) itrWait.next())); | |
346 } | |
347 } | |
348 } | |
349 | |
350 public boolean equals(Object obj) { | |
351 if ((obj != null) && (obj instanceof ObjectReferenceImpl)) { | |
352 ObjectReferenceImpl other = (ObjectReferenceImpl)obj; | |
353 return (ref().equals(other.ref())) && | |
354 super.equals(obj); | |
355 } else { | |
356 return false; | |
357 } | |
358 } | |
359 | |
360 public int hashCode() { | |
361 return saObject.hashCode(); | |
362 } | |
363 | |
364 public String toString() { | |
365 return "instance of " + referenceType().name() + "(id=" + uniqueID() + ")"; | |
366 } | |
367 } |