2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.vm;
20 import java.util.Date;
21 import java.util.Locale;
22 import java.util.Optional;
24 import gov.nasa.jpf.Config;
25 import gov.nasa.jpf.JPF;
26 import gov.nasa.jpf.JPFException;
27 import gov.nasa.jpf.JPFListener;
28 import gov.nasa.jpf.vm.AnnotationInfo.EnumValue;
29 import gov.nasa.jpf.vm.serialize.UnknownJPFClass;
32 * MJIEnv is the call environment for "native" methods, i.e. code that
33 * is executed by the VM, not by JPF.
35 * Since library abstractions are supposed to be "user code", we provide
36 * this class as a (little bit of) insulation towards the inner JPF workings.
38 * There are two APIs exported by this class. The public methods (like
39 * getStringObject) don't expose JPF internals, and can be used from non
40 * gov.nasa.jpf.vm NativePeer classes). The rest is package-default
41 * and can be used to fiddle around as much as you like to (if you are in
44 * Note that MJIEnv objects are now per-ThreadInfo (i.e. the variable
45 * call envionment only includes MethodInfo and ClassInfo), which means
46 * MJIEnv can be used in non-native methods (but only carefully, if you
47 * don't need mi or ciMth).
49 * Note also this only works because we are not getting recursive in
50 * native method calls. In fact, the whole DirectCallStackFrame / repeatTopInstruction
51 * mechanism is there to turn logial recursion (JPF calling native, calling
52 * JPF, calling native,..) into iteration. Otherwise we couldn't backtrack
55 public static final int NULL = 0;
58 ClassInfo ciMth; // the ClassInfo of the method this is called from
63 // those are various attributes set by the execution. note that
64 // NativePeer.invoke never gets recursive in a roundtrip (at least if
65 // used correctly, so we don't have to be afraid to overwrite any of these
69 // exception to be thrown upon return from native method
70 // NOTE: this is only transient - don't expect this to be preserved over
71 // transition boundaries
74 MJIEnv (ThreadInfo ti) {
77 // set those here so that we don't have an inconsistent state between
78 // creation of an MJI object and the first native method call in
79 // this thread (where any access to the heap or sa would bomb)
90 public JPF getJPF () {
94 public boolean isBigEndianPlatform(){
95 return vm.isBigEndianPlatform();
98 public void addListener (JPFListener l){
99 vm.getJPF().addListener(l);
102 public void removeListener (JPFListener l){
103 vm.getJPF().removeListener(l);
106 public Config getConfig() {
107 return vm.getConfig();
114 public void forceState (){
115 getSystemState().setForced(true);
118 public void ignoreTransition () {
119 getSystemState().setIgnored(true);
122 public boolean isArray (int objref) {
123 return heap.get(objref).isArray();
126 public int getArrayLength (int objref) {
127 if (isArray(objref)) {
128 return heap.get(objref).arrayLength();
130 throwException("java.lang.IllegalArgumentException");
136 public String getArrayType (int objref) {
137 return heap.get(objref).getArrayType();
140 public int getArrayTypeSize (int objref) {
141 return Types.getTypeSize(getArrayType(objref));
144 //=== various attribute accessors ============================================
145 // we only support some attribute APIs here, since MJIEnv adds little value
146 // other than hiding the ElementInfo access. If the client already has
147 // an ElementInfo reference, it should use that one to retrieve/enumerate/set
148 // attributes since this avoids repeated Heap.get() calls
150 //--- object attributes
152 public boolean hasObjectAttr (int objref){
154 ElementInfo ei = heap.get(objref);
155 return ei.hasObjectAttr();
161 public boolean hasObjectAttr (int objref, Class<?> type){
163 ElementInfo ei = heap.get(objref);
164 return ei.hasObjectAttr(type);
171 * this returns all of them - use either if you know there will be only
172 * one attribute at a time, or check/process result with ObjectList
174 public Object getObjectAttr (int objref){
176 ElementInfo ei = heap.get(objref);
177 return ei.getObjectAttr();
183 * this replaces all of them - use only if you know
184 * - there will be only one attribute at a time
185 * - you obtained the value you set by a previous getXAttr()
186 * - you constructed a multi value list with ObjectList.createList()
188 public void setObjectAttr (int objref, Object a){
190 ElementInfo ei = heap.get(objref);
195 public void addObjectAttr (int objref, Object a){
197 ElementInfo ei = heap.getModifiable(objref);
204 * this only returns the first attr of this type, there can be more
205 * if you don't use client private types or the provided type is too general
207 public <T> T getObjectAttr (int objref, Class<T> attrType){
208 ElementInfo ei = heap.get(objref);
209 return ei.getObjectAttr(attrType);
212 //--- field attributes
214 public boolean hasFieldAttr (int objref){
216 ElementInfo ei = heap.get(objref);
217 return ei.hasFieldAttr();
223 public boolean hasFieldAttr (int objref, Class<?> type){
225 ElementInfo ei = heap.get(objref);
226 return ei.hasFieldAttr(type);
233 * this returns all of them - use either if you know there will be only
234 * one attribute at a time, or check/process result with ObjectList
236 public Object getFieldAttr (int objref, String fname){
237 ElementInfo ei = heap.get(objref);
238 FieldInfo fi = ei.getFieldInfo(fname);
240 return ei.getFieldAttr(fi);
242 throw new JPFException("no such field: " + fname);
247 * this replaces all of them - use only if you know
248 * - there will be only one attribute at a time
249 * - you obtained the value you set by a previous getXAttr()
250 * - you constructed a multi value list with ObjectList.createList()
252 public void setFieldAttr (int objref, String fname, Object a){
254 ElementInfo ei = heap.get(objref);
255 FieldInfo fi = ei.getFieldInfo(fname);
256 ei.setFieldAttr(fi, a);
260 public void addFieldAttr (int objref, String fname, Object a){
262 ElementInfo ei = heap.getModifiable(objref);
263 FieldInfo fi = ei.getFieldInfo(fname);
264 ei.addFieldAttr(fi, a);
270 * this only returns the first attr of this type, there can be more
271 * if you don't use client private types or the provided type is too general
273 public <T> T getFieldAttr (int objref, String fname, Class<T> attrType){
274 ElementInfo ei = heap.get(objref);
275 FieldInfo fi = ei.getFieldInfo(fname);
277 return ei.getFieldAttr(fi, attrType);
279 throw new JPFException("no such field: " + fname);
286 public boolean hasElementdAttr (int objref){
288 ElementInfo ei = heap.get(objref);
289 return ei.hasElementAttr();
295 public boolean hasElementAttr (int objref, Class<?> type){
297 ElementInfo ei = heap.get(objref);
298 return ei.hasElementAttr(type);
305 * this returns all of them - use either if you know there will be only
306 * one attribute at a time, or check/process result with ObjectList
308 public Object getElementAttr (int objref, int idx){
309 ElementInfo ei = heap.get(objref);
310 return ei.getElementAttr(idx);
314 * this replaces all of them - use only if you know
315 * - there will be only one attribute at a time
316 * - you obtained the value you set by a previous getXAttr()
317 * - you constructed a multi value list with ObjectList.createList()
319 public void setElementAttr (int objref, int idx, Object a){
320 ElementInfo ei = heap.get(objref);
321 ei.setElementAttr(idx, a);
324 public void addElementAttr (int objref, int idx, Object a){
325 ElementInfo ei = heap.getModifiable(objref);
326 ei.addElementAttr(idx, a);
331 * this only returns the first attr of this type, there can be more
332 * if you don't use client private types or the provided type is too general
334 public <T> T getElementAttr (int objref, int idx, Class<T> attrType){
336 ElementInfo ei = heap.get(objref);
337 return ei.getElementAttr(idx, attrType);
348 // the instance field setters
349 public void setBooleanField (int objref, String fname, boolean val) {
350 heap.getModifiable(objref).setBooleanField(fname, val);
353 public boolean getBooleanField (int objref, String fname) {
354 return heap.get(objref).getBooleanField(fname);
357 public boolean getBooleanArrayElement (int objref, int index) {
358 return heap.get(objref).getBooleanElement(index);
361 public void setBooleanArrayElement (int objref, int index, boolean value) {
362 heap.getModifiable(objref).setBooleanElement(index, value);
366 public void setByteField (int objref, String fname, byte val) {
367 heap.getModifiable(objref).setByteField(fname, val);
370 public byte getByteField (int objref, String fname) {
371 return heap.get(objref).getByteField(fname);
374 public void setCharField (int objref, String fname, char val) {
375 heap.getModifiable(objref).setCharField(fname, val);
378 public char getCharField (int objref, String fname) {
379 return heap.get(objref).getCharField(fname);
382 public void setDoubleField (int objref, String fname, double val) {
383 heap.getModifiable(objref).setDoubleField(fname, val);
386 public double getDoubleField (int objref, String fname) {
387 return heap.get(objref).getDoubleField(fname);
390 public void setFloatField (int objref, String fname, float val) {
391 heap.getModifiable(objref).setFloatField(fname, val);
394 public float getFloatField (int objref, String fname) {
395 return heap.get(objref).getFloatField(fname);
399 public void setByteArrayElement (int objref, int index, byte value) {
400 heap.getModifiable(objref).setByteElement(index, value);
403 public byte getByteArrayElement (int objref, int index) {
404 return heap.get(objref).getByteElement(index);
407 public void setCharArrayElement (int objref, int index, char value) {
408 heap.getModifiable(objref).setCharElement(index, value);
411 public void setIntArrayElement (int objref, int index, int value) {
412 heap.getModifiable(objref).setIntElement(index, value);
415 public void setShortArrayElement (int objref, int index, short value) {
416 heap.getModifiable(objref).setShortElement(index, value);
419 public void setFloatArrayElement (int objref, int index, float value) {
420 heap.getModifiable(objref).setFloatElement(index, value);
423 public float getFloatArrayElement (int objref, int index) {
424 return heap.get(objref).getFloatElement(index);
427 public double getDoubleArrayElement (int objref, int index) {
428 return heap.get(objref).getDoubleElement(index);
430 public void setDoubleArrayElement (int objref, int index, double value) {
431 heap.getModifiable(objref).setDoubleElement(index, value);
434 public short getShortArrayElement (int objref, int index) {
435 return heap.get(objref).getShortElement(index);
438 public int getIntArrayElement (int objref, int index) {
439 return heap.get(objref).getIntElement(index);
442 public char getCharArrayElement (int objref, int index) {
443 return heap.get(objref).getCharElement(index);
446 public void setIntField (int objref, String fname, int val) {
447 ElementInfo ei = heap.getModifiable(objref);
448 ei.setIntField(fname, val);
451 // these two are the workhorses
452 public void setDeclaredIntField (int objref, String refType, String fname, int val) {
453 ElementInfo ei = heap.getModifiable(objref);
454 ei.setDeclaredIntField(fname, refType, val);
457 public int getIntField (int objref, String fname) {
458 ElementInfo ei = heap.get(objref);
459 return ei.getIntField(fname);
462 public int getDeclaredIntField (int objref, String refType, String fname) {
463 ElementInfo ei = heap.get(objref);
464 return ei.getDeclaredIntField(fname, refType);
467 // these two are the workhorses
468 public void setDeclaredReferenceField (int objref, String refType, String fname, int val) {
469 ElementInfo ei = heap.getModifiable(objref);
470 ei.setDeclaredReferenceField(fname, refType, val);
473 public void setReferenceField (int objref, String fname, int ref) {
474 ElementInfo ei = heap.getModifiable(objref);
475 ei.setReferenceField(fname, ref);
478 public int getReferenceField (int objref, String fname) {
479 ElementInfo ei = heap.get(objref);
480 return ei.getReferenceField(fname);
483 // we need this in case of a masked field
484 public int getReferenceField (int objref, FieldInfo fi) {
485 ElementInfo ei = heap.get(objref);
486 return ei.getReferenceField(fi);
489 public String getStringField (int objref, String fname){
490 int ref = getReferenceField(objref, fname);
491 return getStringObject(ref);
494 // the box object accessors (should probably test for the appropriate class)
495 public boolean getBooleanValue (int objref) {
496 return getBooleanField(objref, "value");
499 public byte getByteValue (int objref) {
500 return getByteField(objref, "value");
503 public char getCharValue (int objref) {
504 return getCharField(objref, "value");
507 public short getShortValue (int objref) {
508 return getShortField(objref, "value");
511 public int getIntValue (int objref) {
512 return getIntField(objref, "value");
515 public long getLongValue (int objref) {
516 return getLongField(objref, "value");
519 public float getFloatValue (int objref) {
520 return getFloatField(objref, "value");
523 public double getDoubleValue (int objref) {
524 return getDoubleField(objref, "value");
528 public void setLongArrayElement (int objref, int index, long value) {
529 heap.getModifiable(objref).setLongElement(index, value);
532 public long getLongArrayElement (int objref, int index) {
533 return heap.get(objref).getLongElement(index);
536 public void setLongField (int objref, String fname, long val) {
537 ElementInfo ei = heap.getModifiable(objref);
538 ei.setLongField(fname, val);
541 // public void setLongField (int objref, String refType, String fname, long val) {
542 // ElementInfo ei = heap.get(objref);
543 // ei.setLongField(fname, refType, val);
546 public long getLongField (int objref, String fname) {
547 ElementInfo ei = heap.get(objref);
548 return ei.getLongField(fname);
551 // public long getLongField (int objref, String refType, String fname) {
552 // ElementInfo ei = heap.get(objref);
553 // return ei.getLongField(fname, refType);
556 public void setReferenceArrayElement (int objref, int index, int eRef) {
557 heap.getModifiable(objref).setReferenceElement(index, eRef);
560 public int getReferenceArrayElement (int objref, int index) {
561 return heap.get(objref).getReferenceElement(index);
564 public void setShortField (int objref, String fname, short val) {
565 ElementInfo ei = heap.getModifiable(objref);
566 ei.setShortField(fname, val);
569 public short getShortField (int objref, String fname) {
570 ElementInfo ei = heap.get(objref);
571 return ei.getShortField(fname);
575 * NOTE - this doesn't support element type checks or overlapping in-array copy
577 public void arrayCopy (int srcRef, int srcPos, int dstRef, int dstPos, int len){
578 ElementInfo eiSrc = heap.get(srcRef);
579 ElementInfo eiDst = heap.get(dstRef);
581 eiDst.arrayCopy(eiSrc, srcPos, dstPos, len);
584 public String getTypeName (int objref) {
585 return heap.get(objref).getType();
588 public boolean isInstanceOf (int objref, String clsName) {
589 ClassInfo ci = getClassInfo(objref);
590 return ci.isInstanceOf(clsName);
593 public boolean isInstanceOf (int objref, ClassInfo cls) {
594 ClassInfo ci = getClassInfo(objref);
595 return ci.isInstanceOf(cls);
598 //--- the static field accessors
599 // NOTE - it is the callers responsibility to ensure the class is
600 // properly initialized, since calling <clinit> requires a roundtrip
601 // (i.e. cannot be done synchronously from one of the following methods)
603 // <2do> this uses the current system CL, we should probably use an explicit CL argument
605 public void setStaticBooleanField (String clsName, String fname,
607 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
608 ci.getStaticElementInfo().setBooleanField(fname, value);
610 public void setStaticBooleanField (int clsObjRef, String fname, boolean val) {
611 ElementInfo cei = getStaticElementInfo(clsObjRef);
612 cei.setBooleanField(fname, val);
615 public boolean getStaticBooleanField (String clsName, String fname) {
616 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
617 return ci.getStaticElementInfo().getBooleanField(fname);
620 public void setStaticByteField (String clsName, String fname, byte value) {
621 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
622 ci.getStaticElementInfo().setByteField(fname, value); }
624 public byte getStaticByteField (String clsName, String fname) {
625 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
626 return ci.getStaticElementInfo().getByteField(fname);
629 public void setStaticCharField (String clsName, String fname, char value) {
630 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
631 ci.getStaticElementInfo().setCharField(fname, value); }
633 public char getStaticCharField (String clsName, String fname) {
634 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
635 return ci.getStaticElementInfo().getCharField(fname);
638 public void setStaticDoubleField (String clsName, String fname, double val) {
639 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
640 ci.getStaticElementInfo().setDoubleField(fname, val);
643 public double getStaticDoubleField (String clsName, String fname) {
644 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
645 return ci.getStaticElementInfo().getDoubleField(fname);
648 public double getStaticDoubleField (int clsObjRef, String fname) {
649 ElementInfo cei = getStaticElementInfo(clsObjRef);
650 return cei.getDoubleField(fname);
653 public double getStaticDoubleField (ClassInfo ci, String fname) {
654 ElementInfo ei = ci.getStaticElementInfo();
655 return ei.getDoubleField(fname);
658 public void setStaticFloatField (String clsName, String fname, float val) {
659 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
660 ci.getStaticElementInfo().setFloatField(fname, val);
663 public float getStaticFloatField (String clsName, String fname) {
664 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
665 return ci.getStaticElementInfo().getFloatField(fname);
668 public void setStaticIntField (String clsName, String fname, int val) {
669 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
670 ci.getStaticElementInfo().setIntField(fname, val);
673 public void setStaticIntField (int clsObjRef, String fname, int val) {
674 ElementInfo cei = getStaticElementInfo(clsObjRef);
675 cei.setIntField(fname, val);
678 public int getStaticIntField (String clsName, String fname) {
679 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
680 return ci.getStaticElementInfo().getIntField(fname);
683 public int getStaticIntField (int clsObjRef, String fname) {
684 ElementInfo cei = getStaticElementInfo(clsObjRef);
685 return cei.getIntField(fname);
688 public int getStaticIntField (ClassInfo ci, String fname) {
689 ElementInfo ei = ci.getStaticElementInfo();
690 return ei.getIntField(fname);
693 public void setStaticLongField (String clsName, String fname, long value) {
694 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
695 ci.getStaticElementInfo().setLongField(fname, value);
698 public void setStaticLongField (int clsObjRef, String fname, long val) {
699 ElementInfo cei = getModifiableStaticElementInfo(clsObjRef);
700 cei.setLongField(fname, val);
703 public long getStaticLongField (int clsRef, String fname) {
704 ClassInfo ci = getReferredClassInfo(clsRef);
705 return getStaticLongField(ci, fname);
708 public long getStaticLongField (String clsName, String fname) {
709 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
710 return getStaticLongField(ci, fname);
713 public long getStaticLongField (ClassInfo ci, String fname){
714 ElementInfo ei = ci.getStaticElementInfo();
715 return ei.getLongField(fname);
718 public void setStaticReferenceField (String clsName, String fname, int objref) {
719 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
721 // <2do> - we should REALLY check for type compatibility here
722 ci.getModifiableStaticElementInfo().setReferenceField(fname, objref);
725 public void setStaticReferenceField (int clsObjRef, String fname, int objref) {
726 ElementInfo cei = getModifiableStaticElementInfo(clsObjRef);
728 // <2do> - we should REALLY check for type compatibility here
729 cei.setReferenceField(fname, objref);
732 public int getStaticReferenceField (String clsName, String fname) {
733 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
734 return ci.getStaticElementInfo().getReferenceField(fname);
737 public int getStaticReferenceField (int clsObjRef, String fname) {
738 ElementInfo cei = getStaticElementInfo(clsObjRef);
739 return cei.getReferenceField(fname);
742 public int getStaticReferenceField (ClassInfo ci, String fname){
743 return ci.getStaticElementInfo().getReferenceField(fname);
746 public short getStaticShortField (String clsName, String fname) {
747 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
748 return ci.getStaticElementInfo().getShortField(fname);
751 public char[] getStringChars (int objRef){
752 if (objRef != MJIEnv.NULL) {
753 ElementInfo ei = getElementInfo(objRef);
754 return ei.getStringChars();
763 * turn JPF String object into a VM String object
764 * (this is a method available for non gov..jvm NativePeer classes)
766 public String getStringObject (int objRef) {
767 if (objRef != MJIEnv.NULL) {
768 ElementInfo ei = getElementInfo(objRef);
769 return ei.asString();
776 public String[] getStringArrayObject (int aRef){
779 if (aRef == NULL) return sa;
781 ClassInfo aci = getClassInfo(aRef);
783 ClassInfo eci = aci.getComponentClassInfo();
784 if (eci.getName().equals("java.lang.String")){
785 int len = getArrayLength(aRef);
786 sa = new String[len];
788 for (int i=0; i<len; i++){
789 int sRef = getReferenceArrayElement(aRef,i);
790 sa[i] = getStringObject(sRef);
796 throw new IllegalArgumentException("not a String[] array: " + aci.getName());
799 throw new IllegalArgumentException("not an array reference: " + aci.getName());
803 public Date getDateObject (int objref) {
804 if (objref != MJIEnv.NULL) {
805 ElementInfo ei = getElementInfo(objref);
806 if (ei.getClassInfo().getName().equals("java.util.Date")) {
807 // <2do> this is not complete yet
808 long fastTime = ei.getLongField("fastTime");
809 Date d = new Date(fastTime);
812 throw new JPFException("not a Date object reference: " + ei);
820 public Object[] getArgumentArray (int argRef) {
821 Object[] args = null;
822 if (argRef == NULL) return args;
824 int nArgs = getArrayLength(argRef);
825 args = new Object[nArgs];
827 for (int i=0; i<nArgs; i++){
828 int aref = getReferenceArrayElement(argRef,i);
829 ClassInfo ci = getClassInfo(aref);
830 String clsName = ci.getName();
831 if (clsName.equals("java.lang.Boolean")){
832 args[i] = Boolean.valueOf(getBooleanField(aref,"value"));
833 } else if (clsName.equals("java.lang.Integer")){
834 args[i] = Integer.valueOf(getIntField(aref,"value"));
835 } else if (clsName.equals("java.lang.Double")){
836 args[i] = Double.valueOf(getDoubleField(aref,"value"));
837 } else if (clsName.equals("java.lang.String")){
838 args[i] = getStringObject(aref);
845 public Boolean getBooleanObject (int objref){
846 return Boolean.valueOf(getBooleanField(objref, "value"));
849 public Byte getByteObject (int objref){
850 return new Byte(getByteField(objref, "value"));
853 public Character getCharObject (int objref){
854 return new Character(getCharField(objref, "value"));
857 public Short getShortObject (int objref){
858 return new Short(getShortField(objref, "value"));
861 public Integer getIntegerObject (int objref){
862 return new Integer(getIntField(objref, "value"));
865 public Long getLongObject (int objref){
866 return new Long(getLongField(objref, "value"));
869 public Float getFloatObject (int objref){
870 return new Float(getFloatField(objref, "value"));
873 public Double getDoubleObject (int objref){
874 return new Double(getDoubleField(objref, "value"));
877 // danger - the returned arrays could be used to modify contents of stored objects
879 public byte[] getByteArrayObject (int objref) {
880 ElementInfo ei = getElementInfo(objref);
881 byte[] a = ei.asByteArray();
886 public char[] getCharArrayObject (int objref) {
887 ElementInfo ei = getElementInfo(objref);
888 char[] a = ei.asCharArray();
893 public short[] getShortArrayObject (int objref) {
894 ElementInfo ei = getElementInfo(objref);
895 short[] a = ei.asShortArray();
900 public int[] getIntArrayObject (int objref) {
901 ElementInfo ei = getElementInfo(objref);
902 int[] a = ei.asIntArray();
907 public long[] getLongArrayObject (int objref) {
908 ElementInfo ei = getElementInfo(objref);
909 long[] a = ei.asLongArray();
914 public float[] getFloatArrayObject (int objref) {
915 ElementInfo ei = getElementInfo(objref);
916 float[] a = ei.asFloatArray();
921 public double[] getDoubleArrayObject (int objref) {
922 ElementInfo ei = getElementInfo(objref);
923 double[] a = ei.asDoubleArray();
928 public boolean[] getBooleanArrayObject (int objref) {
929 ElementInfo ei = getElementInfo(objref);
930 boolean[] a = ei.asBooleanArray();
935 public int[] getReferenceArrayObject (int objref){
936 ElementInfo ei = getElementInfo(objref);
937 int[] a = ei.asReferenceArray();
942 public boolean canLock (int objref) {
943 ElementInfo ei = getElementInfo(objref);
945 return ei.canLock(ti);
948 public int newBooleanArray (int size) {
949 return heap.newArray("Z", size, ti).getObjectRef();
952 public int newByteArray (int size) {
953 return heap.newArray("B", size, ti).getObjectRef();
956 public int newByteArray (byte[] buf){
957 ElementInfo eiArray = heap.newArray("B", buf.length, ti);
958 for (int i=0; i<buf.length; i++){
959 eiArray.setByteElement( i, buf[i]);
961 return eiArray.getObjectRef();
964 public int newCharArray (int size) {
965 return heap.newArray("C", size, ti).getObjectRef();
968 public int newCharArray (char[] buf){
969 ElementInfo eiArray = heap.newArray("C", buf.length, ti);
970 for (int i=0; i<buf.length; i++){
971 eiArray.setCharElement( i, buf[i]);
973 return eiArray.getObjectRef();
976 public int newShortArray (int size) {
977 return heap.newArray("S", size, ti).getObjectRef();
980 public int newShortArray (short[] buf){
981 ElementInfo eiArray = heap.newArray("S", buf.length, ti);
982 for (int i=0; i<buf.length; i++){
983 eiArray.setShortElement(i, buf[i]);
985 return eiArray.getObjectRef();
988 public int newDoubleArray (int size) {
989 return heap.newArray("D", size, ti).getObjectRef();
992 public int newDoubleArray (double[] buf){
993 ElementInfo eiArray = heap.newArray("D", buf.length, ti);
994 for (int i=0; i<buf.length; i++){
995 eiArray.setDoubleElement(i, buf[i]);
997 return eiArray.getObjectRef();
1000 public int newFloatArray (int size) {
1001 return heap.newArray("F", size, ti).getObjectRef();
1004 public int newFloatArray (float[] buf){
1005 ElementInfo eiArray = heap.newArray("F", buf.length, ti);
1006 for (int i=0; i<buf.length; i++){
1007 eiArray.setFloatElement( i, buf[i]);
1009 return eiArray.getObjectRef();
1012 public int newIntArray (int size) {
1013 return heap.newArray("I", size, ti).getObjectRef();
1016 public int newIntArray (int[] buf){
1017 ElementInfo eiArray = heap.newArray("I", buf.length, ti);
1018 for (int i=0; i<buf.length; i++){
1019 eiArray.setIntElement( i, buf[i]);
1021 return eiArray.getObjectRef();
1024 public int newLongArray (int size) {
1025 return heap.newArray("J", size, ti).getObjectRef();
1028 public int newLongArray (long[] buf){
1029 ElementInfo eiArray = heap.newArray("J", buf.length, ti);
1030 for (int i=0; i<buf.length; i++){
1031 eiArray.setLongElement( i, buf[i]);
1033 return eiArray.getObjectRef();
1036 public int newObjectArray (String elementClsName, int size) {
1037 if (!elementClsName.endsWith(";")) {
1038 elementClsName = Types.getTypeSignature(elementClsName, false);
1041 return heap.newArray(elementClsName, size, ti).getObjectRef();
1044 public ElementInfo newElementInfo (ClassInfo ci) throws ClinitRequired {
1045 if (ci.initializeClass(ti)){
1046 throw new ClinitRequired(ci);
1049 return heap.newObject(ci, ti);
1053 * check if the ClassInfo is properly initialized
1054 * if yes, create a new instance of it but don't call any ctor
1055 * if no, throw a ClinitRequired exception
1057 public int newObject (ClassInfo ci) throws ClinitRequired {
1058 ElementInfo ei = newElementInfo(ci);
1059 return ei.getObjectRef();
1063 * this creates a new object without checking if the ClassInfo needs
1064 * initialization. This is useful in a context that already
1065 * is aware and handles re-execution
1067 public int newObjectOfUncheckedClass (ClassInfo ci){
1068 ElementInfo ei = heap.newObject(ci, ti);
1069 return ei.getObjectRef();
1072 public ElementInfo newElementInfo (String clsName) throws ClinitRequired, UnknownJPFClass {
1073 ClassInfo ci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
1075 return newElementInfo(ci);
1077 throw new UnknownJPFClass(clsName);
1081 public int newObject (String clsName) throws ClinitRequired, UnknownJPFClass {
1082 ElementInfo ei = newElementInfo(clsName);
1083 return (ei != null) ? ei.getObjectRef() : NULL;
1086 public int newString (String s) {
1090 return heap.newString(s, ti).getObjectRef();
1094 public int newStringArray (String[] a){
1095 int aref = newObjectArray("Ljava/lang/String;", a.length);
1097 for (int i=0; i<a.length; i++){
1098 setReferenceArrayElement(aref, i, newString(a[i]));
1104 public int newString (int arrayRef) {
1105 String t = getArrayType(arrayRef);
1108 if ("C".equals(t)) { // character array
1109 char[] ca = getCharArrayObject(arrayRef);
1111 } else if ("B".equals(t)) { // byte array
1112 byte[] ba = getByteArrayObject(arrayRef);
1120 return newString(s);
1123 public String format (int fmtRef, int argRef){
1124 String format = getStringObject(fmtRef);
1125 int len = getArrayLength(argRef);
1126 Object[] arg = new Object[len];
1128 for (int i=0; i<len; i++){
1129 int ref = getReferenceArrayElement(argRef,i);
1131 String clsName = getClassName(ref);
1132 if (clsName.equals("java.lang.String")) {
1133 arg[i] = getStringObject(ref);
1134 } else if (clsName.equals("java.lang.Boolean")){
1135 arg[i] = getBooleanObject(ref);
1136 } else if (clsName.equals("java.lang.Byte")) {
1137 arg[i] = getByteObject(ref);
1138 } else if (clsName.equals("java.lang.Character")) {
1139 arg[i] = getCharObject(ref);
1140 } else if (clsName.equals("java.lang.Short")) {
1141 arg[i] = getShortObject(ref);
1142 } else if (clsName.equals("java.lang.Integer")) {
1143 arg[i] = getIntegerObject(ref);
1144 } else if (clsName.equals("java.lang.Long")) {
1145 arg[i] = getLongObject(ref);
1146 } else if (clsName.equals("java.lang.Float")) {
1147 arg[i] = getFloatObject(ref);
1148 } else if (clsName.equals("java.lang.Double")) {
1149 arg[i] = getDoubleObject(ref);
1151 // need a toString() here
1156 return String.format(format,arg);
1159 public String format (Locale l,int fmtRef, int argRef){
1160 String format = getStringObject(fmtRef);
1161 int len = getArrayLength(argRef);
1162 Object[] arg = new Object[len];
1164 for (int i=0; i<len; i++){
1165 int ref = getReferenceArrayElement(argRef,i);
1167 String clsName = getClassName(ref);
1168 if (clsName.equals("java.lang.String")) {
1169 arg[i] = getStringObject(ref);
1170 } else if (clsName.equals("java.lang.Byte")) {
1171 arg[i] = getByteObject(ref);
1172 } else if (clsName.equals("java.lang.Character")) {
1173 arg[i] = getCharObject(ref);
1174 } else if (clsName.equals("java.lang.Short")) {
1175 arg[i] = getShortObject(ref);
1176 } else if (clsName.equals("java.lang.Integer")) {
1177 arg[i] = getIntegerObject(ref);
1178 } else if (clsName.equals("java.lang.Long")) {
1179 arg[i] = getLongObject(ref);
1180 } else if (clsName.equals("java.lang.Float")) {
1181 arg[i] = getFloatObject(ref);
1182 } else if (clsName.equals("java.lang.Double")) {
1183 arg[i] = getDoubleObject(ref);
1185 // need a toString() here
1191 return String.format(l,format,arg);
1195 public int newBoolean (boolean b){
1196 return getStaticReferenceField("java.lang.Boolean", b ? "TRUE" : "FALSE");
1199 public int newInteger (int n){
1200 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Integer"), ti);
1201 ei.setIntField("value",n);
1202 return ei.getObjectRef();
1205 public int newLong (long l){
1206 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Long"), ti);
1207 ei.setLongField("value",l);
1208 return ei.getObjectRef();
1211 public int newDouble (double d){
1212 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Double"), ti);
1213 ei.setDoubleField("value",d);
1214 return ei.getObjectRef();
1217 public int newFloat (float f){
1218 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Float"), ti);
1219 ei.setFloatField("value",f);
1220 return ei.getObjectRef();
1223 public int newByte (byte b){
1224 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Byte"), ti);
1225 ei.setByteField("value",b);
1226 return ei.getObjectRef();
1229 public int newShort (short s){
1230 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Short"), ti);
1231 ei.setShortField("value",s);
1232 return ei.getObjectRef();
1235 public int newCharacter (char c){
1236 ElementInfo ei = heap.newObject(ClassLoaderInfo.getSystemResolvedClassInfo("java.lang.Character"), ti);
1237 ei.setCharField("value",c);
1238 return ei.getObjectRef();
1242 public boolean notify (int objref) {
1243 // objref can't be NULL since the corresponding INVOKE would have failed
1244 ElementInfo ei = getModifiableElementInfo(objref);
1248 public boolean notify (ElementInfo ei) {
1249 if (!ei.isLockedBy(ti)){
1250 throwException("java.lang.IllegalMonitorStateException",
1251 "un-synchronized notify");
1255 return ei.notifies(getSystemState(), ti);
1258 public boolean notifyAll (int objref) {
1259 // objref can't be NULL since the corresponding INVOKE would have failed
1260 ElementInfo ei = getElementInfo(objref);
1261 return notifyAll(ei);
1264 public boolean notifyAll (ElementInfo ei) {
1265 if (!ei.isLockedBy(ti)){
1266 throwException("java.lang.IllegalMonitorStateException",
1267 "un-synchronized notifyAll");
1271 return ei.notifiesAll();
1274 public void registerPinDown(int objref){
1275 heap.registerPinDown(objref);
1277 public void registerPinDown (ElementInfo ei){
1278 registerPinDown(ei.getObjectRef());
1281 public void releasePinDown(int objref){
1282 heap.releasePinDown(objref);
1284 public void releasePinDown (ElementInfo ei){
1285 releasePinDown(ei.getObjectRef());
1289 * use this whenever a peer performs an operation on a class that might not be initialized yet
1290 * Do a repeatInvocation() in this case
1292 public boolean requiresClinitExecution(ClassInfo ci) {
1293 return ci.initializeClass(ti);
1297 * repeat execution of the instruction that caused a native method call
1298 * NOTE - this does NOT mean it's the NEXT executed insn, since the native method
1299 * might have pushed direct call frames on the stack before asking us to repeat it.
1301 public void repeatInvocation () {
1305 public boolean isInvocationRepeated() {
1310 public boolean setNextChoiceGenerator (ChoiceGenerator<?> cg){
1311 return vm.getSystemState().setNextChoiceGenerator(cg);
1314 public void setMandatoryNextChoiceGenerator(ChoiceGenerator<?> cg, String failMsg){
1315 vm.getSystemState().setMandatoryNextChoiceGenerator(cg, failMsg);
1318 public ChoiceGenerator<?> getChoiceGenerator () {
1319 return vm.getSystemState().getChoiceGenerator();
1322 // note this only makes sense if we actually do return something
1323 public void setReturnAttribute (Object attr) {
1328 * return attr list of all arguments. Use ObjectList to retrieve values
1331 * NOTE - this can only be called from a native method context, since
1332 * otherwise the top frame is the callee
1334 public Object[] getArgAttributes () {
1335 StackFrame caller = getCallerStackFrame();
1336 return caller.getArgumentAttrs(mi);
1339 public Object getReturnAttribute() {
1343 // if any of the next methods is called from the bottom
1344 // half of a CG method, you might want to check if another thread
1345 // or a listener has already set an exception you don't want to override
1346 // (this is for instance used in Thread.stop())
1348 public void throwException (int xRef){
1349 assert isInstanceOf(xRef, "java.lang.Throwable");
1350 exceptionRef = xRef;
1353 public void throwException (String clsName) {
1354 ClassInfo ciX = ClassInfo.getInitializedClassInfo(clsName, ti);
1355 assert ciX.isInstanceOf("java.lang.Throwable") : ciX;
1356 exceptionRef = ti.createException(ciX, null, NULL);
1359 public void throwException (String clsName, String details) {
1360 ClassInfo ciX = ClassInfo.getInitializedClassInfo(clsName, ti);
1361 assert ciX.isInstanceOf("java.lang.Throwable");
1362 exceptionRef = ti.createException(ciX, details, NULL);
1365 public void throwAssertion (String details) {
1366 throwException("java.lang.AssertionError", details);
1369 public void throwInterrupt(){
1370 throwException("java.lang.InterruptedException");
1373 public void stopThread(){
1374 stopThreadWithException(MJIEnv.NULL);
1377 public void stopThreadWithException (int xRef){
1378 // this will call throwException(xRef) with the proper Throwable
1379 ti.setStopped(xRef);
1382 void setCallEnvironment (MethodInfo mi) {
1386 ciMth = mi.getClassInfo();
1395 // we should NOT reset exceptionRef here because it might have been set
1396 // at the beginning of the transition. It gets reset upon return from the
1398 //exceptionRef = NULL;
1401 void clearCallEnvironment () {
1402 setCallEnvironment(null);
1405 ElementInfo getStaticElementInfo (int clsObjRef) {
1406 ClassInfo ci = getReferredClassInfo( clsObjRef);
1408 return ci.getStaticElementInfo();
1414 ElementInfo getModifiableStaticElementInfo (int clsObjRef) {
1415 ClassInfo ci = getReferredClassInfo( clsObjRef);
1417 return ci.getModifiableStaticElementInfo();
1424 ClassInfo getClassInfo () {
1428 public ClassInfo getReferredClassInfo (int clsObjRef) {
1429 ElementInfo ei = getElementInfo(clsObjRef);
1430 if (ei.getClassInfo().getName().equals("java.lang.Class")) {
1431 int ciId = ei.getIntField( ClassInfo.ID_FIELD);
1432 int clref = ei.getReferenceField("classLoader");
1434 ElementInfo eiCl = getElementInfo(clref);
1435 int cliId = eiCl.getIntField(ClassLoaderInfo.ID_FIELD);
1437 ClassLoaderInfo cli = getVM().getClassLoader(cliId);
1438 ClassInfo referredCi = cli.getClassInfo(ciId);
1443 throw new JPFException("not a java.lang.Class object: " + ei);
1447 public ClassInfo getClassInfo (int objref) {
1448 ElementInfo ei = getElementInfo(objref);
1450 return ei.getClassInfo();
1456 public String getClassName (int objref) {
1457 return getClassInfo(objref).getName();
1460 public Heap getHeap () {
1461 return vm.getHeap();
1464 public ElementInfo getElementInfo (int objref) {
1465 return heap.get(objref);
1468 public ElementInfo getModifiableElementInfo (int objref) {
1469 return heap.getModifiable(objref);
1473 public int getStateId () {
1474 return VM.getVM().getStateId();
1477 void clearException(){
1478 exceptionRef = MJIEnv.NULL;
1481 public int peekException () {
1482 return exceptionRef;
1485 public int popException () {
1486 int ret = exceptionRef;
1487 exceptionRef = NULL;
1491 public boolean hasException(){
1492 return (exceptionRef != NULL);
1495 public boolean hasPendingInterrupt(){
1496 return (exceptionRef != NULL && isInstanceOf(exceptionRef, "java.lang.InterruptedException"));
1499 //-- time is managed by the VM
1500 public long currentTimeMillis(){
1501 return vm.currentTimeMillis();
1504 public long nanoTime(){
1505 return vm.nanoTime();
1508 //--- those are not public since they refer to JPF internals
1509 public KernelState getKernelState () {
1510 return VM.getVM().getKernelState();
1513 public MethodInfo getMethodInfo () {
1517 public Instruction getInstruction () {
1522 * It returns the ClassLoaderInfo corresponding to the given classloader object
1525 public ClassLoaderInfo getClassLoaderInfo(int clObjRef) {
1526 if(clObjRef == MJIEnv.NULL) {
1530 int cliId = heap.get(clObjRef).getIntField(ClassLoaderInfo.ID_FIELD);
1531 return getVM().getClassLoader(cliId);
1534 // <2do> that's not correct - it should return the current SystemClassLoader, NOT the startup SystemClassLoader
1535 // (we can instantiate them explicitly)
1536 public ClassLoaderInfo getSystemClassLoaderInfo() {
1537 return ti.getSystemClassLoaderInfo();
1540 public SystemState getSystemState () {
1541 return ti.getVM().getSystemState();
1544 public ApplicationContext getApplicationContext (){
1545 return ti.getApplicationContext();
1548 public ThreadInfo getThreadInfo () {
1553 * NOTE - callers have to be prepared this might return null in case
1554 * the thread got already terminated
1556 public ThreadInfo getThreadInfoForId (int id){
1557 return vm.getThreadList().getThreadInfoForId(id);
1560 public ThreadInfo getLiveThreadInfoForId (int id){
1561 ThreadInfo ti = vm.getThreadList().getThreadInfoForId(id);
1562 if (ti != null && ti.isAlive()){
1570 * NOTE - callers have to be prepared this might return null in case
1571 * the thread got already terminated
1573 public ThreadInfo getThreadInfoForObjRef (int id){
1574 return vm.getThreadList().getThreadInfoForObjRef(id);
1577 public ThreadInfo getLiveThreadInfoForObjRef (int id){
1578 ThreadInfo ti = vm.getThreadList().getThreadInfoForObjRef(id);
1579 if (ti != null && ti.isAlive()){
1588 public ThreadInfo[] getLiveThreads(){
1589 return getVM().getLiveThreads();
1592 // <2do> - naming? not very intuitive
1593 void lockNotified (int objref) {
1594 ElementInfo ei = getModifiableElementInfo(objref);
1595 ei.lockNotified(ti);
1598 public int liftNativeAnnotationValue(String ftype, Object v) {
1599 if (v instanceof String){
1600 return newString((String)v);
1601 } else if (v instanceof Boolean){
1602 return valueOfBoolean((Boolean)v);
1603 } else if (v instanceof Integer) {
1604 return valueOfInteger((Integer)v);
1605 } else if (v instanceof Long){
1606 return valueOfLong((Long)v);
1607 } else if (v instanceof Float){
1608 return newFloat((Float) v);
1609 } else if (v instanceof Short){
1610 return valueOfShort((Short)v);
1611 } else if (v instanceof Character){
1612 return valueOfCharacter((Character)v);
1613 } else if (v instanceof Byte){
1614 return valueOfByte((Byte)v);
1615 } else if (v instanceof Double){
1616 return newDouble((Double)v);
1618 Optional<Integer> ref = liftAnnotationReferenceValue(v, ftype);
1619 if(ref.isPresent()) {
1622 throwException("java.lang.InternalError", "AnnotationElement type not supported: " + ftype);
1628 Optional<Integer> liftAnnotationReferenceValue(Object v, String ftype) {
1629 if (v instanceof AnnotationInfo.EnumValue){ // an enum constant
1630 int eref = makeAnnotationEnumRef((EnumValue) v);
1631 return Optional.of(eref);
1633 } else if (v instanceof AnnotationInfo.ClassValue){ // a class
1634 String clsName = v.toString();
1635 ClassInfo cci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
1636 // <2do> should throw ClassNotFoundError here if cci is null
1638 if (!cci.isInitialized()){
1639 throw new ClinitRequired(cci);
1642 int cref = cci.getClassObjectRef();
1643 return Optional.of(cref);
1645 } else if (v.getClass().isArray()){ // ..or arrays thereof
1646 Object[] a = (Object[])v;
1649 if (ftype.equals("java.lang.String[]")){
1650 aref = newObjectArray("Ljava/lang/String;", a.length);
1651 for (int i=0; i<a.length; i++){
1652 setReferenceArrayElement(aref,i,newString(a[i].toString()));
1654 } else if (ftype.equals("int[]")){
1655 aref = newIntArray(a.length);
1656 for (int i=0; i<a.length; i++){
1657 setIntArrayElement(aref,i,((Number)a[i]).intValue());
1659 } else if (ftype.equals("boolean[]")){
1660 aref = newBooleanArray(a.length);
1661 for (int i=0; i<a.length; i++){
1662 setBooleanArrayElement(aref,i,((Boolean)a[i]).booleanValue());
1664 } else if (ftype.equals("long[]")){
1665 aref = newLongArray(a.length);
1666 for (int i=0; i<a.length; i++){
1667 setLongArrayElement(aref,i,((Number)a[i]).longValue());
1669 } else if (ftype.equals("double[]")){
1670 aref = newDoubleArray(a.length);
1671 for (int i=0; i<a.length; i++){
1672 setDoubleArrayElement(aref,i,((Number)a[i]).doubleValue());
1674 } else if(ftype.equals("char[]")) {
1675 aref = newCharArray(a.length);
1676 for (int i=0; i<a.length; i++){
1677 setCharArrayElement(aref,i,((Character)a[i]).charValue());
1679 } else if(ftype.equals("short[]")) {
1680 aref = newShortArray(a.length);
1681 for (int i=0; i<a.length; i++){
1682 setShortArrayElement(aref,i,((Number)a[i]).shortValue());
1684 } else if(ftype.equals("byte[]")) {
1685 aref = newByteArray(a.length);
1686 for (int i=0; i<a.length; i++){
1687 setByteArrayElement(aref,i,((Number)a[i]).byteValue());
1689 } else if(ftype.equals("float[]")) {
1690 aref = newFloatArray(a.length);
1691 for (int i=0; i<a.length; i++){
1692 setFloatArrayElement(aref,i,((Number)a[i]).floatValue());
1694 } else if (ftype.equals("java.lang.Class[]")){
1695 aref = newObjectArray("java.lang.Class", a.length);
1696 for (int i=0; i<a.length; i++){
1697 String clsName = ((AnnotationInfo.ClassValue)a[i]).getName();
1698 ClassInfo cci = ClassLoaderInfo.getCurrentResolvedClassInfo(clsName);
1699 if (!cci.isInitialized()){
1700 throw new ClinitRequired(cci);
1702 int cref = cci.getClassObjectRef();
1703 setReferenceArrayElement(aref,i,cref);
1706 String typeName = ftype.substring(0, ftype.length() - 2);
1707 ClassInfo elemType = ClassLoaderInfo.getCurrentResolvedClassInfo(typeName);
1708 aref = newObjectArray(typeName, a.length);
1709 if(elemType.isEnum()) {
1710 for(int i = 0; i < a.length; i++) {
1711 setReferenceArrayElement(aref, i, makeAnnotationEnumRef((EnumValue) a[i]));
1715 for(int i = 0; i < a.length; i++) {
1716 setReferenceArrayElement(aref, i, makeAnnotationProxy((AnnotationInfo) a[i]));
1722 return Optional.of(aref);
1724 return Optional.empty();
1727 } else if(v instanceof AnnotationInfo) {
1728 return Optional.of(makeAnnotationProxy((AnnotationInfo) v));
1730 return Optional.empty();
1734 void initAnnotationProxyField (int proxyRef, FieldInfo fi, Object v) throws ClinitRequired {
1735 String fname = fi.getName();
1736 String ftype = fi.getType();
1738 if (v instanceof String){
1739 setReferenceField(proxyRef, fname, newString((String)v));
1740 } else if (v instanceof Boolean){
1741 setBooleanField(proxyRef, fname, ((Boolean)v).booleanValue());
1742 } else if (v instanceof Integer){
1743 setIntField(proxyRef, fname, ((Integer)v).intValue());
1744 } else if (v instanceof Long){
1745 setLongField(proxyRef, fname, ((Long)v).longValue());
1746 } else if (v instanceof Float){
1747 setFloatField(proxyRef, fname, ((Float)v).floatValue());
1748 } else if (v instanceof Short){
1749 setShortField(proxyRef, fname, ((Short)v).shortValue());
1750 } else if (v instanceof Character){
1751 setCharField(proxyRef, fname, ((Character)v).charValue());
1752 } else if (v instanceof Byte){
1753 setByteField(proxyRef, fname, ((Byte)v).byteValue());
1754 } else if (v instanceof Double){
1755 setDoubleField(proxyRef, fname, ((Double)v).doubleValue());
1757 Optional<Integer> ref = liftAnnotationReferenceValue(v, ftype);
1758 if(ref.isPresent()) {
1759 setReferenceField(proxyRef, fname, ref.get());
1761 throwException("java.lang.InternalError", "AnnotationElement type not supported: " + ftype);
1766 private int makeAnnotationEnumRef(AnnotationInfo.EnumValue v) {
1767 AnnotationInfo.EnumValue ev = (AnnotationInfo.EnumValue)v;
1768 String eCls = ev.getEnumClassName();
1769 String eConst = ev.getEnumConstName();
1771 ClassInfo eci = ClassLoaderInfo.getCurrentResolvedClassInfo(eCls);
1772 if (!eci.isInitialized()){
1773 throw new ClinitRequired(eci);
1776 StaticElementInfo sei = eci.getStaticElementInfo();
1777 int eref = sei.getReferenceField(eConst);
1781 int newAnnotationProxy (ClassInfo aciProxy, AnnotationInfo ai) throws ClinitRequired {
1783 int proxyRef = newObject(aciProxy);
1785 // init fields of the new object from the AnnotationInfo
1786 for (AnnotationInfo.Entry e : ai.getEntries()){
1787 Object v = e.getValue();
1788 String fname = e.getKey();
1789 FieldInfo fi = aciProxy.getInstanceField(fname);
1790 initAnnotationProxyField(proxyRef, fi, v);
1796 int newAnnotationProxies (AnnotationInfo[] ai) throws ClinitRequired {
1798 if ((ai != null) && (ai.length > 0)){
1799 int aref = newObjectArray("Ljava/lang/annotation/Annotation;", ai.length);
1800 for (int i=0; i<ai.length; i++){
1801 int ar = makeAnnotationProxy(ai[i]);
1802 setReferenceArrayElement(aref, i, ar);
1807 // on demand init (not too many programs use annotation reflection)
1808 int aref = getStaticReferenceField("java.lang.Class", "emptyAnnotations");
1810 aref = newObjectArray("Ljava/lang/annotation/Annotation;", 0);
1811 setStaticReferenceField("java.lang.Class", "emptyAnnotations", aref);
1817 private int makeAnnotationProxy(AnnotationInfo annotationInfo) {
1818 ClassInfo aci = ClassLoaderInfo.getCurrentResolvedClassInfo(annotationInfo.getName());
1819 ClassInfo aciProxy = aci.getAnnotationProxy();
1821 int ar = newAnnotationProxy(aciProxy, annotationInfo);
1825 public void handleClinitRequest (ClassInfo ci) {
1826 ThreadInfo ti = getThreadInfo();
1828 // NOTE: we have to repeat no matter what, since this is called from
1829 // a handler context (if we only had to create a class object w/o
1830 // calling clinit, we can't just go on)
1831 ci.initializeClass(ti);
1835 public StackFrame getCallerStackFrame() {
1836 // since native methods are now executed within their own stack frames
1837 // we provide a little helper to get the caller
1838 return ti.getLastNonSyntheticStackFrame();
1841 public StackFrame getModifiableCallerStackFrame() {
1842 // since native methods are now executed within their own stack frames
1843 // we provide a little helper to get the caller
1844 return ti.getModifiableLastNonSyntheticStackFrame();
1848 public int valueOfBoolean(boolean b) {
1849 return BoxObjectCacheManager.valueOfBoolean(ti, b);
1852 public int valueOfByte(byte b) {
1853 return BoxObjectCacheManager.valueOfByte(ti, b);
1856 public int valueOfCharacter(char c) {
1857 return BoxObjectCacheManager.valueOfCharacter(ti, c);
1860 public int valueOfShort(short s) {
1861 return BoxObjectCacheManager.valueOfShort(ti, s);
1864 public int valueOfInteger(int i) {
1865 return BoxObjectCacheManager.valueOfInteger(ti, i);
1868 public int valueOfLong(long l) {
1869 return BoxObjectCacheManager.valueOfLong(ti, l);