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.io.IOException;
21 import java.io.InputStream;
22 import java.util.ArrayList;
23 import java.util.HashMap;
26 import gov.nasa.jpf.Config;
27 import gov.nasa.jpf.annotation.MJI;
30 * MJI NativePeer class for java.lang.Class library abstraction
32 public class JPF_java_lang_Class extends NativePeer {
34 static final String FIELD_CLASSNAME = "java.lang.reflect.Field";
35 static final String METHOD_CLASSNAME = "java.lang.reflect.Method";
36 static final String CONSTRUCTOR_CLASSNAME = "java.lang.reflect.Constructor";
38 public static boolean init (Config conf){
39 // we create Method and Constructor objects, so we better make sure these
40 // classes are initialized (they already might be)
41 JPF_java_lang_reflect_Method.init(conf);
42 JPF_java_lang_reflect_Constructor.init(conf);
47 public boolean isArray____Z (MJIEnv env, int robj) {
48 ClassInfo ci = env.getReferredClassInfo( robj);
53 public int getComponentType____Ljava_lang_Class_2 (MJIEnv env, int robj) {
54 if (isArray____Z(env, robj)) {
55 ThreadInfo ti = env.getThreadInfo();
56 Instruction insn = ti.getPC();
57 ClassInfo ci = env.getReferredClassInfo( robj).getComponentClassInfo();
59 if (ci.initializeClass(ti)){
60 env.repeatInvocation();
64 return ci.getClassObjectRef();
71 public boolean isInstance__Ljava_lang_Object_2__Z (MJIEnv env, int robj,
73 ElementInfo sei = env.getStaticElementInfo(robj);
74 ClassInfo ci = sei.getClassInfo();
75 ClassInfo ciOther = env.getClassInfo(r1);
76 return (ciOther.isInstanceOf(ci));
80 public boolean isInterface____Z (MJIEnv env, int robj){
81 ClassInfo ci = env.getReferredClassInfo( robj);
82 return ci.isInterface();
86 public boolean isAssignableFrom__Ljava_lang_Class_2__Z (MJIEnv env, int rcls,
88 ElementInfo sei1 = env.getStaticElementInfo(rcls);
89 ClassInfo ci1 = sei1.getClassInfo();
91 ElementInfo sei2 = env.getStaticElementInfo(r1);
92 ClassInfo ci2 = sei2.getClassInfo();
94 return ci2.isInstanceOf( ci1);
98 public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
99 ClassInfo ci = env.getReferredClassInfo( robj);
100 AnnotationInfo[] ai = ci.getAnnotations();
103 return env.newAnnotationProxies(ai);
104 } catch (ClinitRequired x){
105 env.handleClinitRequest(x.getRequiredClassInfo());
110 // TODO: Fix for Groovy's model-checking
111 private static int getParameterizedTypeImplObj(String[] parameterizedTypes, String ownerType,
112 MJIEnv env, int actObjRef, int rawObjRef) {
114 ThreadInfo ti = env.getThreadInfo();
115 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
116 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl");
117 // Create a new object of type ParameterizedTypeImpl
118 int paramTypeRef = env.newObject(ci);
119 ElementInfo ei = env.getModifiableElementInfo(paramTypeRef);
120 // Get field information and fill out the fields
122 ei.setReferenceField("rawType", rawObjRef);
124 // actualTypeArguments
125 int[] types = new int[parameterizedTypes.length];
126 for(int j = 0; j < parameterizedTypes.length; j++) {
127 types[j] = getTypeVariableImplObject(env, actObjRef, parameterizedTypes[j]);
129 int aRef = env.newObjectArray("Ljava/lang/reflect/Type;", parameterizedTypes.length);
130 // Set references for every array element
131 for (int j = 0; j < parameterizedTypes.length; j++) {
132 env.setReferenceArrayElement(aRef, j, types[j]);
134 ei.setReferenceField("actualTypeArguments", aRef);
137 if (ownerType != null) {
138 ClassInfo oci = ClassLoaderInfo.getCurrentResolvedClassInfo(ownerType);
139 if (!oci.isRegistered()) {
140 oci.registerClass(ti);
142 ei.setReferenceField("ownerType", oci.getClassObjectRef());
144 ei.setReferenceField("ownerType", MJIEnv.NULL);
150 private static int getTypeVariableImplObject(MJIEnv env, int objRef, String parameterizedType) {
152 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
153 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
155 int typeVarRef = env.newObject(ci);
156 ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
157 // genericDeclaration contains this java.lang.reflect.Method object
158 ei.setReferenceField("genericDeclaration", objRef);
159 ei.setReferenceField("name", env.newString(parameterizedType));
165 public int getGenericSuperclass____Ljava_lang_reflect_Type_2 (MJIEnv env, int robj){
166 ClassInfo ci = env.getReferredClassInfo( robj);
167 ClassInfo sci = ci.getSuperClass();
169 String[] typeVars = sci.getGenericTypeVariableNames();
170 // Not a generic class
171 if (typeVars.length == 0) {
172 return sci.getClassObjectRef();
174 String className = sci.getName();
175 String ownerType = Types.getOwnerClassName(className);
176 int gRef = getParameterizedTypeImplObj(typeVars, ownerType, env, ci.getClassObjectRef(), sci.getClassObjectRef());
185 public int getGenericInterfaces_____3Ljava_lang_reflect_Type_2 (MJIEnv env, int robj) {
186 ClassInfo ci = env.getReferredClassInfo(robj);
187 int aref = MJIEnv.NULL;
188 ThreadInfo ti = env.getThreadInfo();
189 // contrary to the API doc, this only returns the interfaces directly
190 // implemented by this class, not it's bases
191 // <2do> this is not exactly correct, since the interfaces should be ordered
192 Set<ClassInfo> interfaces = ci.getInterfaceClassInfos();
194 aref = env.newObjectArray("Ljava/lang/Class;", interfaces.size());
197 for (ClassInfo ifc: interfaces){
198 if (Types.isGenericSignature(ifc.getGenericSignature())) {
199 String className = ifc.getName();
200 String ownerType = Types.getOwnerClassName(className);
201 String[] typeVars = ifc.getGenericTypeVariableNames();
202 int paramTypeObj = getParameterizedTypeImplObj(typeVars, ownerType, env, ci.getClassObjectRef(),
203 ifc.getClassObjectRef());
204 env.setReferenceArrayElement(aref, i++, paramTypeObj);
206 env.setReferenceArrayElement(aref, i++, ifc.getClassObjectRef());
214 public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int robj){
215 // Get the ClassInfo for this class
216 ClassInfo tci = env.getReferredClassInfo(robj);
217 String[] typeVars = tci.getGenericTypeVariableNames();
219 // Return with null if this is not a generic class
220 if (typeVars.length == 0) {
221 int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 0);
224 // Now create a TypeVariableImpl object for every type variable name; get the ClassInfo for TypeVariableImpl
225 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
226 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
227 int[] var = new int[typeVars.length];
229 for(int i = 0; i < typeVars.length; i++) {
230 int typeVarRef = env.newObject(ci);
231 ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
232 ei.setReferenceField("genericDeclaration", tci.getClassObjectRef());
233 ei.setReferenceField("name", env.newString(typeVars[i]));
236 int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVars.length);
238 // Set references for every array element
239 for (int i = 0; i < typeVars.length; i++) {
240 env.setReferenceArrayElement(aRef, i, var[i]);
247 public int getProtectionDomain____Ljava_security_ProtectionDomain_2 (MJIEnv env, int robj) {
248 // Now create a ProtectionDomain object
249 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
250 ClassInfo pdci = cli.getResolvedClassInfo("java.security.ProtectionDomain");
252 int proDomRef = MJIEnv.NULL;
254 TODO: Defer the following to future implementations
255 TODO: Currently Groovy runs well without actually instantiating a ProtectionDomain object properly
256 int proDomRef = env.newObject(pdci);
257 ElementInfo ei = env.getModifiableElementInfo(proDomRef);
258 ei.setReferenceField("codesource", MJIEnv.NULL);
259 ei.setReferenceField("classloader", MJIEnv.NULL);
260 ei.setBooleanField("hasAllPerm", true);
261 ei.setBooleanField("staticPermissions", true);
263 // Load the Permission (AllPermission class)
264 ClassInfo pci = cli.getResolvedClassInfo("java.security.AllPermission");
265 int permRef = env.newObject(pci);
266 ElementInfo pei = env.getModifiableElementInfo(permRef);
267 pei.setReferenceField("name", env.newString("<all permissions>"));
268 ei.setReferenceField("permissions", permRef);*/
272 // TODO: Fix for Groovy's model-checking
275 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj,
277 ClassInfo ci = env.getReferredClassInfo( robj);
278 ClassInfo aci = env.getReferredClassInfo(annoClsRef);
280 AnnotationInfo ai = ci.getAnnotation(aci.getName());
282 ClassInfo aciProxy = aci.getAnnotationProxy();
285 return env.newAnnotationProxy(aciProxy, ai);
286 } catch (ClinitRequired x){
287 env.handleClinitRequest(x.getRequiredClassInfo());
296 public int getPrimitiveClass__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
297 int rcls, int stringRef) {
298 // we don't really have to check for a valid class name here, since
299 // this is a package default method that just gets called from
300 // the clinit of box classes
301 // note this does NOT return the box class (e.g. java.lang.Integer), which
302 // is a normal, functional class, but a primitive class (e.g. 'int') that
303 // is rather a strange beast (not even Object derived)
305 ClassLoaderInfo scli = env.getSystemClassLoaderInfo(); // this is the one responsible for builtin classes
306 String primClsName = env.getStringObject(stringRef); // always initialized
308 ClassInfo ci = scli.getResolvedClassInfo(primClsName);
309 return ci.getClassObjectRef();
313 public boolean desiredAssertionStatus____Z (MJIEnv env, int robj) {
314 ClassInfo ci = env.getReferredClassInfo(robj);
315 return ci.desiredAssertionStatus();
318 public static int getClassObject (MJIEnv env, ClassInfo ci){
319 ThreadInfo ti = env.getThreadInfo();
320 Instruction insn = ti.getPC();
322 if (ci.initializeClass(ti)){
323 env.repeatInvocation();
327 StaticElementInfo ei = ci.getStaticElementInfo();
328 int ref = ei.getClassObjectRef();
334 public int forName__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
337 if (clsNameRef == MJIEnv.NULL){
338 env.throwException("java.lang.NullPointerException", "no class name provided");
342 String clsName = env.getStringObject(clsNameRef);
344 if (clsName.isEmpty()){
345 env.throwException("java.lang.ClassNotFoundException", "empty class name");
349 ThreadInfo ti = env.getThreadInfo();
350 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
351 // class of the method that includes the invocation of Class.forName()
352 ClassInfo cls = mi.getClassInfo();
355 // for array type, the component terminal must be resolved
356 if(clsName.charAt(0)=='[') {
357 name = Types.getComponentTerminal(clsName);
362 // make the classloader of the class including the invocation of
363 // Class.forName() resolve the class with the given name
365 cls.resolveReferencedClass(name);
366 } catch(LoadOnJPFRequired lre) {
367 env.repeatInvocation();
371 // The class obtained here is the same as the resolved one, except
372 // if it represents an array type
373 ClassInfo ci = cls.getClassLoaderInfo().getResolvedClassInfo(clsName);
375 return getClassObject(env, ci);
379 * this is an example of a native method issuing direct calls - otherwise known
381 * We don't have to deal with class init here anymore, since this is called
382 * via the class object of the class to instantiate
385 public int newInstance____Ljava_lang_Object_2 (MJIEnv env, int robj) {
386 ThreadInfo ti = env.getThreadInfo();
387 DirectCallStackFrame frame = ti.getReturnedDirectCall();
389 ClassInfo ci = env.getReferredClassInfo(robj); // what are we
390 MethodInfo miCtor = ci.getMethod("<init>()V", true); // note there always is one since something needs to call Object()
392 if (frame == null){ // first time around
393 if(ci.isAbstract()){ // not allowed to instantiate
394 env.throwException("java.lang.InstantiationException");
398 // <2do> - still need to handle protected
399 if (miCtor.isPrivate()) {
400 env.throwException("java.lang.IllegalAccessException", "cannot access non-public member of class " + ci.getName());
404 int objRef = env.newObjectOfUncheckedClass(ci); // create the thing
406 frame = miCtor.createDirectCallStackFrame(ti, 1);
407 // note that we don't set this as a reflection call since it is supposed to propagate exceptions
408 frame.setReferenceArgument(0, objRef, null);
409 frame.setLocalReferenceVariable(0, objRef); // (1) store ref for retrieval during re-exec
412 // check if we have to push clinits
413 ci.initializeClass(ti);
415 env.repeatInvocation();
418 } else { // re-execution
419 int objRef = frame.getLocalVariable(0); // that's the object ref we set in (1)
425 public int getSuperclass____Ljava_lang_Class_2 (MJIEnv env, int robj) {
426 ClassInfo ci = env.getReferredClassInfo( robj);
427 ClassInfo sci = ci.getSuperClass();
429 return sci.getClassObjectRef();
435 int getMethod (MJIEnv env, int clsRef, ClassInfo ciMethod, String mname, int argTypesRef,
436 boolean isRecursiveLookup, boolean publicOnly) {
438 ClassInfo ci = env.getReferredClassInfo( clsRef);
440 StringBuilder sb = new StringBuilder(mname);
442 int nParams = argTypesRef != MJIEnv.NULL ? env.getArrayLength(argTypesRef) : 0;
443 for (int i=0; i<nParams; i++) {
444 int cRef = env.getReferenceArrayElement(argTypesRef, i);
445 ClassInfo cit = env.getReferredClassInfo( cRef);
446 String tname = cit.getName();
447 String tcode = tname;
448 tcode = Types.getTypeSignature(tcode, false);
452 String fullMthName = sb.toString();
454 MethodInfo mi = ci.getReflectionMethod(fullMthName, isRecursiveLookup);
455 if (mi == null || (publicOnly && !mi.isPublic())) {
456 env.throwException("java.lang.NoSuchMethodException", ci.getName() + '.' + fullMthName);
460 return createMethodObject(env, ciMethod, mi);
464 int createMethodObject (MJIEnv env, ClassInfo objectCi, MethodInfo mi) {
465 // NOTE - we rely on Constructor and Method peers being initialized
467 return JPF_java_lang_reflect_Constructor.createConstructorObject(env, objectCi, mi);
469 return JPF_java_lang_reflect_Method.createMethodObject(env, objectCi, mi);
474 public int getDeclaredMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
475 int nameRef, int argTypesRef) {
476 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
478 env.repeatInvocation();
482 String mname = env.getStringObject(nameRef);
483 return getMethod(env, clsRef, mci, mname, argTypesRef, false, false);
487 public int getDeclaredConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env,
490 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
492 env.repeatInvocation();
496 int ctorRef = getMethod(env,clsRef, mci, "<init>",argTypesRef,false, false);
501 public int getMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
502 int nameRef, int argTypesRef) {
503 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
505 env.repeatInvocation();
509 String mname = env.getStringObject(nameRef);
510 return getMethod( env, clsRef, mci, mname, argTypesRef, true, true);
513 private void addDeclaredMethodsRec (boolean includeSuperClasses, HashMap<String,MethodInfo>methods, ClassInfo ci){
515 if (includeSuperClasses){ // do NOT include Object methods for interfaces
516 ClassInfo sci = ci.getSuperClass();
518 addDeclaredMethodsRec( includeSuperClasses, methods,sci);
522 ClassLoaderInfo cl = ci.getClassLoaderInfo();
523 for (String ifcName : ci.getDirectInterfaceNames()){
524 ClassInfo ici = cl.getResolvedClassInfo(ifcName); // has to be already defined, so no exception
525 addDeclaredMethodsRec( includeSuperClasses, methods,ici);
528 for (MethodInfo mi : ci.getDeclaredMethodInfos()) {
529 // filter out non-public, <clinit> and <init>
530 if (mi.isPublic() && (mi.getName().charAt(0) != '<')) {
531 String mname = mi.getUniqueName();
533 if (!(ci.isInterface() && methods.containsKey(mname))){
534 methods.put(mname, mi);
541 public int getMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
542 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
544 env.repeatInvocation();
548 ClassInfo ci = env.getReferredClassInfo(objref);
550 // collect all the public, non-ctor instance methods
551 if (!ci.isPrimitive()) {
552 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
553 addDeclaredMethodsRec( !ci.isInterface(), methods,ci);
555 int n = methods.size();
556 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", n);
559 for (MethodInfo mi : methods.values()){
560 int mref = createMethodObject(env, mci, mi);
561 env.setReferenceArrayElement(aref,i++,mref);
567 return env.newObjectArray("Ljava/lang/reflect/Method;", 0);
572 public int getDeclaredMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
573 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
575 env.repeatInvocation();
579 ClassInfo ci = env.getReferredClassInfo(objref);
580 MethodInfo[] methodInfos = ci.getDeclaredMethodInfos();
582 // we have to filter out the ctors and the static init
583 int nMth = methodInfos.length;
584 for (int i=0; i<methodInfos.length; i++){
585 if (methodInfos[i].getName().charAt(0) == '<'){
586 methodInfos[i] = null;
591 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", nMth);
593 for (int i=0, j=0; i<methodInfos.length; i++) {
594 if (methodInfos[i] != null){
595 int mref = createMethodObject(env, mci, methodInfos[i]);
596 env.setReferenceArrayElement(aref,j++,mref);
603 int getConstructors (MJIEnv env, int objref, boolean publicOnly){
604 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
606 env.repeatInvocation();
610 ClassInfo ci = env.getReferredClassInfo(objref);
611 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
613 // we have to filter out the ctors and the static init
614 for (MethodInfo mi : ci.getDeclaredMethodInfos()){
615 if (mi.getName().equals("<init>")){
616 if (!publicOnly || mi.isPublic()) {
622 int nCtors = ctors.size();
623 int aref = env.newObjectArray("Ljava/lang/reflect/Constructor;", nCtors);
625 for (int i=0; i<nCtors; i++){
626 env.setReferenceArrayElement(aref, i, createMethodObject(env, mci, ctors.get(i)));
633 public int getConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
634 return getConstructors(env, objref, true);
638 public int getDeclaredConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
639 return getConstructors(env, objref, false);
643 public int getConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env, int clsRef,
645 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
647 env.repeatInvocation();
651 // <2do> should only return a public ctor
652 return getMethod(env,clsRef, mci, "<init>",argTypesRef,false,true);
655 // this is only used for system classes such as java.lang.reflect.Method
656 ClassInfo getInitializedClassInfo (MJIEnv env, String clsName){
657 ThreadInfo ti = env.getThreadInfo();
658 Instruction insn = ti.getPC();
659 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo( clsName);
661 if (ci.initializeClass(ti)){
669 public void initialize0____V (MJIEnv env, int clsObjRef){
670 ClassInfo ci = env.getReferredClassInfo( clsObjRef);
671 ci.initializeClass(ThreadInfo.currentThread);
674 Set<ClassInfo> getInitializedInterfaces (MJIEnv env, ClassInfo ci){
675 ThreadInfo ti = env.getThreadInfo();
676 Instruction insn = ti.getPC();
678 Set<ClassInfo> ifcs = ci.getAllInterfaceClassInfos();
679 for (ClassInfo ciIfc : ifcs){
680 if (ciIfc.initializeClass(ti)){
688 static int createFieldObject (MJIEnv env, FieldInfo fi, ClassInfo fci){
689 int regIdx = JPF_java_lang_reflect_Field.registerFieldInfo(fi);
691 int eidx = env.newObject(fci);
692 ElementInfo ei = env.getModifiableElementInfo(eidx);
693 ei.setIntField("regIdx", regIdx);
699 public int getDeclaredFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int objRef) {
700 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
702 env.repeatInvocation();
706 ClassInfo ci = env.getReferredClassInfo(objRef);
707 int nInstance = ci.getNumberOfDeclaredInstanceFields();
708 int nStatic = ci.getNumberOfStaticFields();
709 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", nInstance + nStatic);
712 for (i=0; i<nStatic; i++) {
713 FieldInfo fi = ci.getStaticField(i);
714 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
717 for (i=0; i<nInstance; i++) {
718 FieldInfo fi = ci.getDeclaredInstanceField(i);
719 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
726 public int getFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef){
727 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
729 env.repeatInvocation();
733 ClassInfo ci = env.getReferredClassInfo(clsRef);
734 // interfaces might not be initialized yet, so we have to check first
735 Set<ClassInfo> ifcs = getInitializedInterfaces( env, ci);
737 env.repeatInvocation();
741 ArrayList<FieldInfo> fiList = new ArrayList<FieldInfo>();
742 for (; ci != null; ci = ci.getSuperClass()){
743 // the host VM returns them in order of declaration, but the spec says there is no guaranteed order so we keep it simple
744 for (FieldInfo fi : ci.getDeclaredInstanceFields()){
749 for (FieldInfo fi : ci.getDeclaredStaticFields()){
756 for (ClassInfo ciIfc : ifcs){
757 for (FieldInfo fi : ciIfc.getDeclaredStaticFields()){
758 fiList.add(fi); // there are no non-public fields in interfaces
762 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", fiList.size());
764 for (FieldInfo fi : fiList){
765 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
771 int getField (MJIEnv env, int clsRef, int nameRef, boolean isRecursiveLookup) {
772 ClassInfo ci = env.getReferredClassInfo( clsRef);
773 String fname = env.getStringObject(nameRef);
776 if (isRecursiveLookup) {
777 fi = ci.getInstanceField(fname);
779 fi = ci.getStaticField(fname);
782 fi = ci.getDeclaredInstanceField(fname);
784 fi = ci.getDeclaredStaticField(fname);
789 env.throwException("java.lang.NoSuchFieldException", fname);
793 // don't do a Field clinit before we know there is such a field
794 ClassInfo fci = getInitializedClassInfo( env, FIELD_CLASSNAME);
796 env.repeatInvocation();
800 return createFieldObject( env, fi, fci);
805 public int getDeclaredField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
806 return getField(env,clsRef,nameRef, false);
810 public int getField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
811 return getField(env,clsRef,nameRef, true);
815 public int getModifiers____I (MJIEnv env, int clsRef){
816 ClassInfo ci = env.getReferredClassInfo(clsRef);
817 return ci.getModifiers();
821 public int getEnumConstants_____3Ljava_lang_Object_2 (MJIEnv env, int clsRef){
822 ClassInfo ci = env.getReferredClassInfo(clsRef);
824 if (env.requiresClinitExecution(ci)){
825 env.repeatInvocation();
829 if (ci.getSuperClass().getName().equals("java.lang.Enum")) {
830 ArrayList<FieldInfo> list = new ArrayList<FieldInfo>();
831 String cName = ci.getName();
833 for (FieldInfo fi : ci.getDeclaredStaticFields()) {
834 if (fi.isFinal() && cName.equals(fi.getType())){
839 int aRef = env.newObjectArray(cName, list.size());
840 StaticElementInfo sei = ci.getStaticElementInfo();
842 for (FieldInfo fi : list){
843 env.setReferenceArrayElement( aRef, i++, sei.getReferenceField(fi));
852 public int getInterfaces_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
853 ClassInfo ci = env.getReferredClassInfo(clsRef);
854 int aref = MJIEnv.NULL;
855 ThreadInfo ti = env.getThreadInfo();
857 // contrary to the API doc, this only returns the interfaces directly
858 // implemented by this class, not it's bases
859 // <2do> this is not exactly correct, since the interfaces should be ordered
860 Set<ClassInfo> interfaces = ci.getInterfaceClassInfos();
861 aref = env.newObjectArray("Ljava/lang/Class;", interfaces.size());
864 for (ClassInfo ifc: interfaces){
865 env.setReferenceArrayElement(aref, i++, ifc.getClassObjectRef());
873 * <2do> needs to load from the classfile location, NOT the MJIEnv (native) class
875 * @author Sebastian Gfeller (sebastian.gfeller@gmail.com)
876 * @author Tihomir Gvero (tihomir.gvero@gmail.com)
879 public int getByteArrayFromResourceStream__Ljava_lang_String_2___3B(MJIEnv env, int clsRef, int nameRef) {
880 String name = env.getStringObject(nameRef);
882 // <2do> this is not loading from the classfile location! fix it
883 InputStream is = env.getClass().getResourceAsStream(name);
887 // We assume that the entire input stream can be read at the moment,
888 // although this could break.
889 byte[] content = null;
891 content = new byte[is.available()];
893 } catch (IOException e) {
894 throw new RuntimeException(e);
896 // Now if everything worked, the content should be in the byte buffer.
897 // We put this buffer into the JPF VM.
898 return env.newByteArray(content);
902 public int getEnclosingClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef) {
903 ClassInfo ciEncl = env.getReferredClassInfo( clsRef).getEnclosingClassInfo();
909 if (ciEncl.initializeClass(env.getThreadInfo())) {
910 env.repeatInvocation();
914 return ciEncl.getClassObjectRef();
918 public int getDeclaredClasses_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
919 ClassInfo ci = env.getReferredClassInfo(clsRef);
920 String[] innerClassNames = ci.getInnerClasses();
921 int aref = MJIEnv.NULL;
922 ThreadInfo ti = env.getThreadInfo();
924 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
925 // class of the method that includes the invocation of Class.getDeclaredClasses
926 ClassInfo cls = mi.getClassInfo();
928 // first resolve all the inner classes
929 int length = innerClassNames.length;
930 ClassInfo[] resolvedInnerClass = new ClassInfo[length];
931 for(int i=0; i<length; i++) {
933 resolvedInnerClass[i] = cls.resolveReferencedClass(innerClassNames[i]);
934 } catch(LoadOnJPFRequired lre) {
935 env.repeatInvocation();
940 aref = env.newObjectArray("Ljava/lang/Class;", innerClassNames.length);
941 for (int i=0; i<length; i++){
942 ClassInfo ici = resolvedInnerClass[i];
943 if (!ici.isRegistered()) {
944 ici.registerClass(ti);
946 env.setReferenceArrayElement(aref, i, ici.getClassObjectRef());
952 private String getCanonicalName (ClassInfo ci){
954 String canonicalName = getCanonicalName(ci.getComponentClassInfo());
955 if (canonicalName != null){
956 return canonicalName + "[]";
961 if (isLocalOrAnonymousClass(ci)) {
964 if (ci.getEnclosingClassInfo() == null){
967 String enclosingName = getCanonicalName(ci.getEnclosingClassInfo());
968 if (enclosingName == null){ return null; }
969 return enclosingName + "." + ci.getSimpleName();
974 public int getCanonicalName____Ljava_lang_String_2 (MJIEnv env, int clsRef){
975 ClassInfo ci = env.getReferredClassInfo(clsRef);
976 return env.newString(getCanonicalName(ci));
980 public boolean isAnnotation____Z (MJIEnv env, int clsObjRef){
981 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
982 return (ci.getModifiers() & 0x2000) != 0;
986 public boolean isAnnotationPresent__Ljava_lang_Class_2__Z (MJIEnv env, int clsObjRef, int annoClsObjRef){
987 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
988 ClassInfo ciAnno = env.getReferredClassInfo(annoClsObjRef);
990 return ci.getAnnotation( ciAnno.getName()) != null;
994 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
995 ClassInfo ci = env.getReferredClassInfo(robj);
998 return env.newAnnotationProxies(ci.getDeclaredAnnotations());
999 } catch (ClinitRequired x){
1000 env.handleClinitRequest(x.getRequiredClassInfo());
1006 public int getEnclosingConstructor____Ljava_lang_reflect_Constructor_2 (MJIEnv env, int robj){
1007 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
1009 env.repeatInvocation();
1012 ClassInfo ci = env.getReferredClassInfo(robj);
1013 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
1015 if ((enclosingMethod != null) && enclosingMethod.isCtor()){
1016 return createMethodObject(env, mci, enclosingMethod);
1022 public int getEnclosingMethod____Ljava_lang_reflect_Method_2 (MJIEnv env, int robj){
1023 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
1025 env.repeatInvocation();
1028 ClassInfo ci = env.getReferredClassInfo(robj);
1029 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
1031 if ((enclosingMethod != null) && !enclosingMethod.isCtor()){
1032 return createMethodObject(env, mci, enclosingMethod);
1038 public boolean isAnonymousClass____Z (MJIEnv env, int robj){
1039 ClassInfo ci = env.getReferredClassInfo(robj);
1040 String cname = null;
1041 if (ci.getName().contains("$")){
1042 cname = ci.getName().substring(ci.getName().lastIndexOf('$') + 1);
1044 return (cname == null) ? false : cname.matches("\\d+?");
1048 public boolean isEnum____Z (MJIEnv env, int robj){
1049 ClassInfo ci = env.getReferredClassInfo(robj);
1053 // Similar to getEnclosingClass() except it returns null for the case of
1056 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef){
1057 ClassInfo ci = env.getReferredClassInfo(clsRef);
1058 if (isLocalOrAnonymousClass(ci)){
1061 return getEnclosingClass____Ljava_lang_Class_2(env, clsRef);
1066 public boolean isLocalClass____Z (MJIEnv env, int robj){
1067 ClassInfo ci = env.getReferredClassInfo(robj);
1068 return isLocalOrAnonymousClass(ci) && !isAnonymousClass____Z(env, robj);
1071 private boolean isLocalOrAnonymousClass (ClassInfo ci){
1072 return (ci.getEnclosingMethodInfo() != null);
1076 public boolean isMemberClass____Z (MJIEnv env, int robj){
1077 ClassInfo ci = env.getReferredClassInfo(robj);
1078 return (ci.getEnclosingClassInfo() != null) && !isLocalOrAnonymousClass(ci);
1082 * Append the package name prefix of the class represented by robj, if the name is not
1083 * absolute. OW, remove leading "/".
1086 public int getResolvedName__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int robj, int resRef){
1087 String rname = env.getStringObject(resRef);
1088 ClassInfo ci = env.getReferredClassInfo(robj);
1089 if (rname == null) {
1092 if (!rname.startsWith("/")) {
1094 while (c.isArray()) {
1095 c = c.getComponentClassInfo();
1097 String baseName = c.getName();
1098 int index = baseName.lastIndexOf('.');
1100 rname = baseName.substring(0, index).replace('.', '/')
1104 rname = rname.substring(1);
1107 return env.newString(rname);