59 protected static class Cache {
60 JDWP.ObjectReference.MonitorInfo monitorInfo = null;
61 }
62
63 private static final Cache noInitCache = new Cache();
64 private static final Cache markerCache = new Cache();
65 private Cache cache = noInitCache;
66
67 private void disableCache() {
68 synchronized (vm.state()) {
69 cache = null;
70 }
71 }
72
73 private void enableCache() {
74 synchronized (vm.state()) {
75 cache = markerCache;
76 }
77 }
78
79 // Override in subclasses
80 protected Cache newCache() {
81 return new Cache();
82 }
83
84 protected Cache getCache() {
85 synchronized (vm.state()) {
86 if (cache == noInitCache) {
87 if (vm.state().isSuspended()) {
88 // Set cache now, otherwise newly created objects are
89 // not cached until resuspend
90 enableCache();
91 } else {
92 disableCache();
93 }
94 }
95 if (cache == markerCache) {
96 cache = newCache();
97 }
98 return cache;
128 // make sure that cache and listener management are synchronized
129 synchronized (vm.state()) {
130 if (cache != null && (vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
131 vm.printTrace("Clearing temporary cache for " + description());
132 }
133 disableCache();
134 if (addedListener) {
135 /*
136 * If a listener was added (i.e. this is not a
137 * ObjectReference that adds a listener on startup),
138 * remove it here.
139 */
140 addedListener = false;
141 return false; // false says remove
142 } else {
143 return true;
144 }
145 }
146 }
147
148 public boolean equals(Object obj) {
149 if ((obj != null) && (obj instanceof ObjectReferenceImpl)) {
150 ObjectReferenceImpl other = (ObjectReferenceImpl)obj;
151 return (ref() == other.ref()) &&
152 super.equals(obj);
153 } else {
154 return false;
155 }
156 }
157
158 public int hashCode() {
159 return(int)ref();
160 }
161
162 public Type type() {
163 return referenceType();
164 }
165
166 public ReferenceType referenceType() {
167 if (type == null) {
168 try {
169 JDWP.ObjectReference.ReferenceType rtinfo =
170 JDWP.ObjectReference.ReferenceType.process(vm, this);
171 type = vm.referenceType(rtinfo.typeID,
172 rtinfo.refTypeTag);
453 } catch (JDWPException exc) {
454 // If already collected, no harm done, no exception
455 if (exc.errorCode() != JDWP.Error.INVALID_OBJECT) {
456 throw exc.toJDIException();
457 }
458 return;
459 }
460 }
461 }
462
463 public boolean isCollected() {
464 try {
465 return JDWP.ObjectReference.IsCollected.process(vm, this).
466 isCollected;
467 } catch (JDWPException exc) {
468 throw exc.toJDIException();
469 }
470 }
471
472 public long uniqueID() {
473 return ref();
474 }
475
476 JDWP.ObjectReference.MonitorInfo jdwpMonitorInfo()
477 throws IncompatibleThreadStateException {
478 JDWP.ObjectReference.MonitorInfo info = null;
479 try {
480 Cache local;
481
482 // getCache() and addlistener() must be synchronized
483 // so that no events are lost.
484 synchronized (vm.state()) {
485 local = getCache();
486
487 if (local != null) {
488 info = local.monitorInfo;
489
490 // Check if there will be something to cache
491 // and there is not already a listener
492 if (info == null && !vm.state().hasListener(this)) {
577 }
578
579 void validateAssignment(ValueContainer destination)
580 throws InvalidTypeException, ClassNotLoadedException {
581
582 /*
583 * Do these simpler checks before attempting a query of the destination's
584 * type which might cause a confusing ClassNotLoadedException if
585 * the destination is primitive or an array.
586 */
587 /*
588 * TO DO: Centralize JNI signature knowledge
589 */
590 if (destination.signature().length() == 1) {
591 throw new InvalidTypeException("Can't assign object value to primitive");
592 }
593 if ((destination.signature().charAt(0) == '[') &&
594 (type().signature().charAt(0) != '[')) {
595 throw new InvalidTypeException("Can't assign non-array value to an array");
596 }
597 if ("void".equals(destination.typeName())) {
598 throw new InvalidTypeException("Can't assign object value to a void");
599 }
600
601 // Validate assignment
602 ReferenceType destType = (ReferenceTypeImpl)destination.type();
603 ReferenceTypeImpl myType = (ReferenceTypeImpl)referenceType();
604 if (!myType.isAssignableTo(destType)) {
605 JNITypeParser parser = new JNITypeParser(destType.signature());
606 String destTypeName = parser.typeName();
607 throw new InvalidTypeException("Can't assign " +
608 type().name() +
609 " to " + destTypeName);
610 }
611 }
612
613 public String toString() {
614 return "instance of " + referenceType().name() + "(id=" + uniqueID() + ")";
615 }
616
617 byte typeValueKey() {
618 return JDWP.Tag.OBJECT;
619 }
620
621 private static boolean isNonVirtual(int options) {
622 return (options & INVOKE_NONVIRTUAL) != 0;
623 }
624 }
|
59 protected static class Cache {
60 JDWP.ObjectReference.MonitorInfo monitorInfo = null;
61 }
62
63 private static final Cache noInitCache = new Cache();
64 private static final Cache markerCache = new Cache();
65 private Cache cache = noInitCache;
66
67 private void disableCache() {
68 synchronized (vm.state()) {
69 cache = null;
70 }
71 }
72
73 private void enableCache() {
74 synchronized (vm.state()) {
75 cache = markerCache;
76 }
77 }
78
79 private boolean isInlineType() {
80 return referenceType().signature().startsWith("Q");
81 }
82
83 // Override in subclasses
84 protected Cache newCache() {
85 return new Cache();
86 }
87
88 protected Cache getCache() {
89 synchronized (vm.state()) {
90 if (cache == noInitCache) {
91 if (vm.state().isSuspended()) {
92 // Set cache now, otherwise newly created objects are
93 // not cached until resuspend
94 enableCache();
95 } else {
96 disableCache();
97 }
98 }
99 if (cache == markerCache) {
100 cache = newCache();
101 }
102 return cache;
132 // make sure that cache and listener management are synchronized
133 synchronized (vm.state()) {
134 if (cache != null && (vm.traceFlags & VirtualMachine.TRACE_OBJREFS) != 0) {
135 vm.printTrace("Clearing temporary cache for " + description());
136 }
137 disableCache();
138 if (addedListener) {
139 /*
140 * If a listener was added (i.e. this is not a
141 * ObjectReference that adds a listener on startup),
142 * remove it here.
143 */
144 addedListener = false;
145 return false; // false says remove
146 } else {
147 return true;
148 }
149 }
150 }
151
152 private boolean isSubstitutable(ObjectReferenceImpl other) {
153 if (referenceType() != other.referenceType()) return false;
154 List<Field> fields = referenceType().fields();
155 for (Field f : fields) {
156 if (f.isStatic()) {
157 fields.remove(f);
158 }
159 }
160 Map<Field,Value> thisFields = getValues(fields);
161 Map<Field,Value> otherFields = other.getValues(fields);
162 for (Field f : fields) {
163 if (!thisFields.get(f).equals(otherFields.get(f))) return false;
164 }
165 return true;
166 }
167
168 public boolean equals(Object obj) {
169 if ((obj != null) && (obj instanceof ObjectReferenceImpl)) {
170 ObjectReferenceImpl other = (ObjectReferenceImpl) obj;
171 if (isInlineType()) {
172 return isSubstitutable(other);
173 } else {
174 return (ref() == other.ref()) &&
175 super.equals(obj);
176 }
177 } else {
178 return false;
179 }
180 }
181
182 public int hashCode() {
183 return(int)ref();
184 }
185
186 public Type type() {
187 return referenceType();
188 }
189
190 public ReferenceType referenceType() {
191 if (type == null) {
192 try {
193 JDWP.ObjectReference.ReferenceType rtinfo =
194 JDWP.ObjectReference.ReferenceType.process(vm, this);
195 type = vm.referenceType(rtinfo.typeID,
196 rtinfo.refTypeTag);
477 } catch (JDWPException exc) {
478 // If already collected, no harm done, no exception
479 if (exc.errorCode() != JDWP.Error.INVALID_OBJECT) {
480 throw exc.toJDIException();
481 }
482 return;
483 }
484 }
485 }
486
487 public boolean isCollected() {
488 try {
489 return JDWP.ObjectReference.IsCollected.process(vm, this).
490 isCollected;
491 } catch (JDWPException exc) {
492 throw exc.toJDIException();
493 }
494 }
495
496 public long uniqueID() {
497 if (isInlineType()) {
498 throw new UnsupportedOperationException("Inline types cannot have unique IDs");
499 }
500 return ref();
501 }
502
503 JDWP.ObjectReference.MonitorInfo jdwpMonitorInfo()
504 throws IncompatibleThreadStateException {
505 JDWP.ObjectReference.MonitorInfo info = null;
506 try {
507 Cache local;
508
509 // getCache() and addlistener() must be synchronized
510 // so that no events are lost.
511 synchronized (vm.state()) {
512 local = getCache();
513
514 if (local != null) {
515 info = local.monitorInfo;
516
517 // Check if there will be something to cache
518 // and there is not already a listener
519 if (info == null && !vm.state().hasListener(this)) {
604 }
605
606 void validateAssignment(ValueContainer destination)
607 throws InvalidTypeException, ClassNotLoadedException {
608
609 /*
610 * Do these simpler checks before attempting a query of the destination's
611 * type which might cause a confusing ClassNotLoadedException if
612 * the destination is primitive or an array.
613 */
614 /*
615 * TO DO: Centralize JNI signature knowledge
616 */
617 if (destination.signature().length() == 1) {
618 throw new InvalidTypeException("Can't assign object value to primitive");
619 }
620 if ((destination.signature().charAt(0) == '[') &&
621 (type().signature().charAt(0) != '[')) {
622 throw new InvalidTypeException("Can't assign non-array value to an array");
623 }
624 if ((destination.signature().charAt(0) == 'Q') &&
625 ref() == 0) {
626 throw new InvalidTypeException("Can't assign null value to an inline type");
627 }
628 if ("void".equals(destination.typeName())) {
629 throw new InvalidTypeException("Can't assign object value to a void");
630 }
631
632 // Validate assignment
633 ReferenceType destType = (ReferenceTypeImpl)destination.type();
634 ReferenceTypeImpl myType = (ReferenceTypeImpl)referenceType();
635 if (!myType.isAssignableTo(destType)) {
636 JNITypeParser parser = new JNITypeParser(destType.signature());
637 String destTypeName = parser.typeName();
638 throw new InvalidTypeException("Can't assign " +
639 type().name() +
640 " to " + destTypeName);
641 }
642 }
643
644 public String toString() {
645 if (isInlineType()) {
646 return "instance of " + referenceType().name();
647 } else {
648 return "instance of " + referenceType().name() + "(id=" + uniqueID() + ")";
649 }
650 }
651
652 byte typeValueKey() {
653 if (isInlineType()) {
654 return JDWP.Tag.INLINE_OBJECT;
655 } else {
656 return JDWP.Tag.OBJECT;
657 }
658 }
659
660 private static boolean isNonVirtual(int options) {
661 return (options & INVOKE_NONVIRTUAL) != 0;
662 }
663 }
|