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 import java.lang.reflect.TypeVariable;
31 import sun.reflect.generics.factory.CoreReflectionFactory;
32 import sun.reflect.generics.factory.GenericsFactory;
33 import sun.reflect.generics.repository.ClassRepository;
34 import sun.reflect.generics.scope.ClassScope;
37 * MJI NativePeer class for java.lang.Class library abstraction
39 public class JPF_java_lang_Class extends NativePeer {
41 static final String FIELD_CLASSNAME = "java.lang.reflect.Field";
42 static final String METHOD_CLASSNAME = "java.lang.reflect.Method";
43 static final String CONSTRUCTOR_CLASSNAME = "java.lang.reflect.Constructor";
45 static final String TYPEVARIABLE_CLASSNAME = "java.lang.reflect.TypeVariable";
47 public static boolean init (Config conf){
48 // we create Method and Constructor objects, so we better make sure these
49 // classes are initialized (they already might be)
50 JPF_java_lang_reflect_Method.init(conf);
51 JPF_java_lang_reflect_Constructor.init(conf);
56 public boolean isArray____Z (MJIEnv env, int robj) {
57 ClassInfo ci = env.getReferredClassInfo( robj);
62 public int getComponentType____Ljava_lang_Class_2 (MJIEnv env, int robj) {
63 if (isArray____Z(env, robj)) {
64 ThreadInfo ti = env.getThreadInfo();
65 Instruction insn = ti.getPC();
66 ClassInfo ci = env.getReferredClassInfo( robj).getComponentClassInfo();
68 if (ci.initializeClass(ti)){
69 env.repeatInvocation();
73 return ci.getClassObjectRef();
80 public boolean isInstance__Ljava_lang_Object_2__Z (MJIEnv env, int robj,
82 ElementInfo sei = env.getStaticElementInfo(robj);
83 ClassInfo ci = sei.getClassInfo();
84 ClassInfo ciOther = env.getClassInfo(r1);
85 return (ciOther.isInstanceOf(ci));
89 public boolean isInterface____Z (MJIEnv env, int robj){
90 ClassInfo ci = env.getReferredClassInfo( robj);
91 return ci.isInterface();
95 public boolean isAssignableFrom__Ljava_lang_Class_2__Z (MJIEnv env, int rcls,
97 ElementInfo sei1 = env.getStaticElementInfo(rcls);
98 ClassInfo ci1 = sei1.getClassInfo();
100 ElementInfo sei2 = env.getStaticElementInfo(r1);
101 ClassInfo ci2 = sei2.getClassInfo();
103 return ci2.isInstanceOf( ci1);
107 public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
108 ClassInfo ci = env.getReferredClassInfo( robj);
109 AnnotationInfo[] ai = ci.getAnnotations();
112 return env.newAnnotationProxies(ai);
113 } catch (ClinitRequired x){
114 env.handleClinitRequest(x.getRequiredClassInfo());
120 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj,
122 ClassInfo ci = env.getReferredClassInfo( robj);
123 ClassInfo aci = env.getReferredClassInfo(annoClsRef);
125 AnnotationInfo ai = ci.getAnnotation(aci.getName());
127 ClassInfo aciProxy = aci.getAnnotationProxy();
130 return env.newAnnotationProxy(aciProxy, ai);
131 } catch (ClinitRequired x){
132 env.handleClinitRequest(x.getRequiredClassInfo());
141 public int getPrimitiveClass__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
142 int rcls, int stringRef) {
143 // we don't really have to check for a valid class name here, since
144 // this is a package default method that just gets called from
145 // the clinit of box classes
146 // note this does NOT return the box class (e.g. java.lang.Integer), which
147 // is a normal, functional class, but a primitive class (e.g. 'int') that
148 // is rather a strange beast (not even Object derived)
150 ClassLoaderInfo scli = env.getSystemClassLoaderInfo(); // this is the one responsible for builtin classes
151 String primClsName = env.getStringObject(stringRef); // always initialized
153 ClassInfo ci = scli.getResolvedClassInfo(primClsName);
154 return ci.getClassObjectRef();
157 // TODO: DIRTY HACKS!
158 /*int createTypeVariableObject (MJIEnv env, ClassInfo objectCi, MethodInfo mi) {
159 // NOTE - we rely on Constructor and Method peers being initialized
161 return JPF_java_lang_reflect_Constructor.createConstructorObject(env, objectCi, mi);
163 return JPF_java_lang_reflect_Method.createMethodObject(env, objectCi, mi);
167 // accessor for factory
168 private GenericsFactory getFactory() {
169 // create scope and factory
170 return CoreReflectionFactory.make(this, ClassScope.make(this));
174 public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int objRef){
175 ClassInfo tci = getInitializedClassInfo(env, TYPEVARIABLE_CLASSNAME);
177 env.repeatInvocation();
180 // Get the object and the type parameters
181 ClassInfo ci = env.getReferredClassInfo(objRef);
182 String signature = ci.getType();
183 ClassRepository genericInfo = ClassRepository.make(signature, getFactory());
184 TypeVariable[] typeVariables = (TypeVariable[]) genericInfo.getTypeParameters();
186 int aref = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVariables.length);
188 for(int i=0, j=0; i<typeVariables.length; i++){
189 if (typeVariables[i] != null) {
190 int mref = env.newObject(ci);
191 env.setReferenceArrayElement(aref,j++,mref);
197 // TODO: DIRTY HACKS!
200 public boolean desiredAssertionStatus____Z (MJIEnv env, int robj) {
201 ClassInfo ci = env.getReferredClassInfo(robj);
202 return ci.desiredAssertionStatus();
205 public static int getClassObject (MJIEnv env, ClassInfo ci){
206 ThreadInfo ti = env.getThreadInfo();
207 Instruction insn = ti.getPC();
209 if (ci.initializeClass(ti)){
210 env.repeatInvocation();
214 StaticElementInfo ei = ci.getStaticElementInfo();
215 int ref = ei.getClassObjectRef();
221 public int forName__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
224 if (clsNameRef == MJIEnv.NULL){
225 env.throwException("java.lang.NullPointerException", "no class name provided");
229 String clsName = env.getStringObject(clsNameRef);
231 if (clsName.isEmpty()){
232 env.throwException("java.lang.ClassNotFoundException", "empty class name");
236 ThreadInfo ti = env.getThreadInfo();
237 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
238 // class of the method that includes the invocation of Class.forName()
239 ClassInfo cls = mi.getClassInfo();
242 // for array type, the component terminal must be resolved
243 if(clsName.charAt(0)=='[') {
244 name = Types.getComponentTerminal(clsName);
249 // make the classloader of the class including the invocation of
250 // Class.forName() resolve the class with the given name
252 cls.resolveReferencedClass(name);
253 } catch(LoadOnJPFRequired lre) {
254 env.repeatInvocation();
258 // The class obtained here is the same as the resolved one, except
259 // if it represents an array type
260 ClassInfo ci = cls.getClassLoaderInfo().getResolvedClassInfo(clsName);
262 return getClassObject(env, ci);
266 * this is an example of a native method issuing direct calls - otherwise known
268 * We don't have to deal with class init here anymore, since this is called
269 * via the class object of the class to instantiate
272 public int newInstance____Ljava_lang_Object_2 (MJIEnv env, int robj) {
273 ThreadInfo ti = env.getThreadInfo();
274 DirectCallStackFrame frame = ti.getReturnedDirectCall();
276 ClassInfo ci = env.getReferredClassInfo(robj); // what are we
277 MethodInfo miCtor = ci.getMethod("<init>()V", true); // note there always is one since something needs to call Object()
279 if (frame == null){ // first time around
280 if(ci.isAbstract()){ // not allowed to instantiate
281 env.throwException("java.lang.InstantiationException");
285 // <2do> - still need to handle protected
286 if (miCtor.isPrivate()) {
287 env.throwException("java.lang.IllegalAccessException", "cannot access non-public member of class " + ci.getName());
291 int objRef = env.newObjectOfUncheckedClass(ci); // create the thing
293 frame = miCtor.createDirectCallStackFrame(ti, 1);
294 // note that we don't set this as a reflection call since it is supposed to propagate exceptions
295 frame.setReferenceArgument(0, objRef, null);
296 frame.setLocalReferenceVariable(0, objRef); // (1) store ref for retrieval during re-exec
299 // check if we have to push clinits
300 ci.initializeClass(ti);
302 env.repeatInvocation();
305 } else { // re-execution
306 int objRef = frame.getLocalVariable(0); // that's the object ref we set in (1)
312 public int getSuperclass____Ljava_lang_Class_2 (MJIEnv env, int robj) {
313 ClassInfo ci = env.getReferredClassInfo( robj);
314 ClassInfo sci = ci.getSuperClass();
316 return sci.getClassObjectRef();
322 int getMethod (MJIEnv env, int clsRef, ClassInfo ciMethod, String mname, int argTypesRef,
323 boolean isRecursiveLookup, boolean publicOnly) {
325 ClassInfo ci = env.getReferredClassInfo( clsRef);
327 StringBuilder sb = new StringBuilder(mname);
329 int nParams = argTypesRef != MJIEnv.NULL ? env.getArrayLength(argTypesRef) : 0;
330 for (int i=0; i<nParams; i++) {
331 int cRef = env.getReferenceArrayElement(argTypesRef, i);
332 ClassInfo cit = env.getReferredClassInfo( cRef);
333 String tname = cit.getName();
334 String tcode = tname;
335 tcode = Types.getTypeSignature(tcode, false);
339 String fullMthName = sb.toString();
341 MethodInfo mi = ci.getReflectionMethod(fullMthName, isRecursiveLookup);
342 if (mi == null || (publicOnly && !mi.isPublic())) {
343 env.throwException("java.lang.NoSuchMethodException", ci.getName() + '.' + fullMthName);
347 return createMethodObject(env, ciMethod, mi);
351 int createMethodObject (MJIEnv env, ClassInfo objectCi, MethodInfo mi) {
352 // NOTE - we rely on Constructor and Method peers being initialized
354 return JPF_java_lang_reflect_Constructor.createConstructorObject(env, objectCi, mi);
356 return JPF_java_lang_reflect_Method.createMethodObject(env, objectCi, mi);
361 public int getDeclaredMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
362 int nameRef, int argTypesRef) {
363 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
365 env.repeatInvocation();
369 String mname = env.getStringObject(nameRef);
370 return getMethod(env, clsRef, mci, mname, argTypesRef, false, false);
374 public int getDeclaredConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env,
377 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
379 env.repeatInvocation();
383 int ctorRef = getMethod(env,clsRef, mci, "<init>",argTypesRef,false, false);
388 public int getMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
389 int nameRef, int argTypesRef) {
390 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
392 env.repeatInvocation();
396 String mname = env.getStringObject(nameRef);
397 return getMethod( env, clsRef, mci, mname, argTypesRef, true, true);
400 private void addDeclaredMethodsRec (boolean includeSuperClasses, HashMap<String,MethodInfo>methods, ClassInfo ci){
402 if (includeSuperClasses){ // do NOT include Object methods for interfaces
403 ClassInfo sci = ci.getSuperClass();
405 addDeclaredMethodsRec( includeSuperClasses, methods,sci);
409 ClassLoaderInfo cl = ci.getClassLoaderInfo();
410 for (String ifcName : ci.getDirectInterfaceNames()){
411 ClassInfo ici = cl.getResolvedClassInfo(ifcName); // has to be already defined, so no exception
412 addDeclaredMethodsRec( includeSuperClasses, methods,ici);
415 for (MethodInfo mi : ci.getDeclaredMethodInfos()) {
416 // filter out non-public, <clinit> and <init>
417 if (mi.isPublic() && (mi.getName().charAt(0) != '<')) {
418 String mname = mi.getUniqueName();
420 if (!(ci.isInterface() && methods.containsKey(mname))){
421 methods.put(mname, mi);
428 public int getMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
429 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
431 env.repeatInvocation();
435 ClassInfo ci = env.getReferredClassInfo(objref);
437 // collect all the public, non-ctor instance methods
438 if (!ci.isPrimitive()) {
439 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
440 addDeclaredMethodsRec( !ci.isInterface(), methods,ci);
442 int n = methods.size();
443 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", n);
446 for (MethodInfo mi : methods.values()){
447 int mref = createMethodObject(env, mci, mi);
448 env.setReferenceArrayElement(aref,i++,mref);
454 return env.newObjectArray("Ljava/lang/reflect/Method;", 0);
459 public int getDeclaredMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
460 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
462 env.repeatInvocation();
466 ClassInfo ci = env.getReferredClassInfo(objref);
467 MethodInfo[] methodInfos = ci.getDeclaredMethodInfos();
469 // we have to filter out the ctors and the static init
470 int nMth = methodInfos.length;
471 for (int i=0; i<methodInfos.length; i++){
472 if (methodInfos[i].getName().charAt(0) == '<'){
473 methodInfos[i] = null;
478 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", nMth);
480 for (int i=0, j=0; i<methodInfos.length; i++) {
481 if (methodInfos[i] != null){
482 int mref = createMethodObject(env, mci, methodInfos[i]);
483 env.setReferenceArrayElement(aref,j++,mref);
490 int getConstructors (MJIEnv env, int objref, boolean publicOnly){
491 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
493 env.repeatInvocation();
497 ClassInfo ci = env.getReferredClassInfo(objref);
498 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
500 // we have to filter out the ctors and the static init
501 for (MethodInfo mi : ci.getDeclaredMethodInfos()){
502 if (mi.getName().equals("<init>")){
503 if (!publicOnly || mi.isPublic()) {
509 int nCtors = ctors.size();
510 int aref = env.newObjectArray("Ljava/lang/reflect/Constructor;", nCtors);
512 for (int i=0; i<nCtors; i++){
513 env.setReferenceArrayElement(aref, i, createMethodObject(env, mci, ctors.get(i)));
520 public int getConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
521 return getConstructors(env, objref, true);
525 public int getDeclaredConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
526 return getConstructors(env, objref, false);
530 public int getConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env, int clsRef,
532 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
534 env.repeatInvocation();
538 // <2do> should only return a public ctor
539 return getMethod(env,clsRef, mci, "<init>",argTypesRef,false,true);
542 // this is only used for system classes such as java.lang.reflect.Method
543 ClassInfo getInitializedClassInfo (MJIEnv env, String clsName){
544 ThreadInfo ti = env.getThreadInfo();
545 Instruction insn = ti.getPC();
546 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo( clsName);
548 if (ci.initializeClass(ti)){
556 public void initialize0____V (MJIEnv env, int clsObjRef){
557 ClassInfo ci = env.getReferredClassInfo( clsObjRef);
558 ci.initializeClass(ThreadInfo.currentThread);
561 Set<ClassInfo> getInitializedInterfaces (MJIEnv env, ClassInfo ci){
562 ThreadInfo ti = env.getThreadInfo();
563 Instruction insn = ti.getPC();
565 Set<ClassInfo> ifcs = ci.getAllInterfaceClassInfos();
566 for (ClassInfo ciIfc : ifcs){
567 if (ciIfc.initializeClass(ti)){
575 static int createFieldObject (MJIEnv env, FieldInfo fi, ClassInfo fci){
576 int regIdx = JPF_java_lang_reflect_Field.registerFieldInfo(fi);
578 int eidx = env.newObject(fci);
579 ElementInfo ei = env.getModifiableElementInfo(eidx);
580 ei.setIntField("regIdx", regIdx);
586 public int getDeclaredFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int objRef) {
587 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
589 env.repeatInvocation();
593 ClassInfo ci = env.getReferredClassInfo(objRef);
594 int nInstance = ci.getNumberOfDeclaredInstanceFields();
595 int nStatic = ci.getNumberOfStaticFields();
596 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", nInstance + nStatic);
599 for (i=0; i<nStatic; i++) {
600 FieldInfo fi = ci.getStaticField(i);
601 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
604 for (i=0; i<nInstance; i++) {
605 FieldInfo fi = ci.getDeclaredInstanceField(i);
606 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
613 public int getFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef){
614 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
616 env.repeatInvocation();
620 ClassInfo ci = env.getReferredClassInfo(clsRef);
621 // interfaces might not be initialized yet, so we have to check first
622 Set<ClassInfo> ifcs = getInitializedInterfaces( env, ci);
624 env.repeatInvocation();
628 ArrayList<FieldInfo> fiList = new ArrayList<FieldInfo>();
629 for (; ci != null; ci = ci.getSuperClass()){
630 // the host VM returns them in order of declaration, but the spec says there is no guaranteed order so we keep it simple
631 for (FieldInfo fi : ci.getDeclaredInstanceFields()){
636 for (FieldInfo fi : ci.getDeclaredStaticFields()){
643 for (ClassInfo ciIfc : ifcs){
644 for (FieldInfo fi : ciIfc.getDeclaredStaticFields()){
645 fiList.add(fi); // there are no non-public fields in interfaces
649 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", fiList.size());
651 for (FieldInfo fi : fiList){
652 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
658 int getField (MJIEnv env, int clsRef, int nameRef, boolean isRecursiveLookup) {
659 ClassInfo ci = env.getReferredClassInfo( clsRef);
660 String fname = env.getStringObject(nameRef);
663 if (isRecursiveLookup) {
664 fi = ci.getInstanceField(fname);
666 fi = ci.getStaticField(fname);
669 fi = ci.getDeclaredInstanceField(fname);
671 fi = ci.getDeclaredStaticField(fname);
676 env.throwException("java.lang.NoSuchFieldException", fname);
680 // don't do a Field clinit before we know there is such a field
681 ClassInfo fci = getInitializedClassInfo( env, FIELD_CLASSNAME);
683 env.repeatInvocation();
687 return createFieldObject( env, fi, fci);
692 public int getDeclaredField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
693 return getField(env,clsRef,nameRef, false);
697 public int getField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
698 return getField(env,clsRef,nameRef, true);
702 public int getModifiers____I (MJIEnv env, int clsRef){
703 ClassInfo ci = env.getReferredClassInfo(clsRef);
704 return ci.getModifiers();
708 public int getEnumConstants_____3Ljava_lang_Object_2 (MJIEnv env, int clsRef){
709 ClassInfo ci = env.getReferredClassInfo(clsRef);
711 if (env.requiresClinitExecution(ci)){
712 env.repeatInvocation();
716 if (ci.getSuperClass().getName().equals("java.lang.Enum")) {
717 ArrayList<FieldInfo> list = new ArrayList<FieldInfo>();
718 String cName = ci.getName();
720 for (FieldInfo fi : ci.getDeclaredStaticFields()) {
721 if (fi.isFinal() && cName.equals(fi.getType())){
726 int aRef = env.newObjectArray(cName, list.size());
727 StaticElementInfo sei = ci.getStaticElementInfo();
729 for (FieldInfo fi : list){
730 env.setReferenceArrayElement( aRef, i++, sei.getReferenceField(fi));
739 public int getInterfaces_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
740 ClassInfo ci = env.getReferredClassInfo(clsRef);
741 int aref = MJIEnv.NULL;
742 ThreadInfo ti = env.getThreadInfo();
744 // contrary to the API doc, this only returns the interfaces directly
745 // implemented by this class, not it's bases
746 // <2do> this is not exactly correct, since the interfaces should be ordered
747 Set<ClassInfo> interfaces = ci.getInterfaceClassInfos();
748 aref = env.newObjectArray("Ljava/lang/Class;", interfaces.size());
751 for (ClassInfo ifc: interfaces){
752 env.setReferenceArrayElement(aref, i++, ifc.getClassObjectRef());
760 * <2do> needs to load from the classfile location, NOT the MJIEnv (native) class
762 * @author Sebastian Gfeller (sebastian.gfeller@gmail.com)
763 * @author Tihomir Gvero (tihomir.gvero@gmail.com)
766 public int getByteArrayFromResourceStream__Ljava_lang_String_2___3B(MJIEnv env, int clsRef, int nameRef) {
767 String name = env.getStringObject(nameRef);
769 // <2do> this is not loading from the classfile location! fix it
770 InputStream is = env.getClass().getResourceAsStream(name);
774 // We assume that the entire input stream can be read at the moment,
775 // although this could break.
776 byte[] content = null;
778 content = new byte[is.available()];
780 } catch (IOException e) {
781 throw new RuntimeException(e);
783 // Now if everything worked, the content should be in the byte buffer.
784 // We put this buffer into the JPF VM.
785 return env.newByteArray(content);
789 public int getEnclosingClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef) {
790 ClassInfo ciEncl = env.getReferredClassInfo( clsRef).getEnclosingClassInfo();
796 if (ciEncl.initializeClass(env.getThreadInfo())) {
797 env.repeatInvocation();
801 return ciEncl.getClassObjectRef();
805 public int getDeclaredClasses_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
806 ClassInfo ci = env.getReferredClassInfo(clsRef);
807 String[] innerClassNames = ci.getInnerClasses();
808 int aref = MJIEnv.NULL;
809 ThreadInfo ti = env.getThreadInfo();
811 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
812 // class of the method that includes the invocation of Class.getDeclaredClasses
813 ClassInfo cls = mi.getClassInfo();
815 // first resolve all the inner classes
816 int length = innerClassNames.length;
817 ClassInfo[] resolvedInnerClass = new ClassInfo[length];
818 for(int i=0; i<length; i++) {
820 resolvedInnerClass[i] = cls.resolveReferencedClass(innerClassNames[i]);
821 } catch(LoadOnJPFRequired lre) {
822 env.repeatInvocation();
827 aref = env.newObjectArray("Ljava/lang/Class;", innerClassNames.length);
828 for (int i=0; i<length; i++){
829 ClassInfo ici = resolvedInnerClass[i];
830 if (!ici.isRegistered()) {
831 ici.registerClass(ti);
833 env.setReferenceArrayElement(aref, i, ici.getClassObjectRef());
839 private String getCanonicalName (ClassInfo ci){
841 String canonicalName = getCanonicalName(ci.getComponentClassInfo());
842 if (canonicalName != null){
843 return canonicalName + "[]";
848 if (isLocalOrAnonymousClass(ci)) {
851 if (ci.getEnclosingClassInfo() == null){
854 String enclosingName = getCanonicalName(ci.getEnclosingClassInfo());
855 if (enclosingName == null){ return null; }
856 return enclosingName + "." + ci.getSimpleName();
861 public int getCanonicalName____Ljava_lang_String_2 (MJIEnv env, int clsRef){
862 ClassInfo ci = env.getReferredClassInfo(clsRef);
863 return env.newString(getCanonicalName(ci));
867 public boolean isAnnotation____Z (MJIEnv env, int clsObjRef){
868 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
869 return (ci.getModifiers() & 0x2000) != 0;
873 public boolean isAnnotationPresent__Ljava_lang_Class_2__Z (MJIEnv env, int clsObjRef, int annoClsObjRef){
874 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
875 ClassInfo ciAnno = env.getReferredClassInfo(annoClsObjRef);
877 return ci.getAnnotation( ciAnno.getName()) != null;
881 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
882 ClassInfo ci = env.getReferredClassInfo(robj);
885 return env.newAnnotationProxies(ci.getDeclaredAnnotations());
886 } catch (ClinitRequired x){
887 env.handleClinitRequest(x.getRequiredClassInfo());
893 public int getEnclosingConstructor____Ljava_lang_reflect_Constructor_2 (MJIEnv env, int robj){
894 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
896 env.repeatInvocation();
899 ClassInfo ci = env.getReferredClassInfo(robj);
900 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
902 if ((enclosingMethod != null) && enclosingMethod.isCtor()){
903 return createMethodObject(env, mci, enclosingMethod);
909 public int getEnclosingMethod____Ljava_lang_reflect_Method_2 (MJIEnv env, int robj){
910 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
912 env.repeatInvocation();
915 ClassInfo ci = env.getReferredClassInfo(robj);
916 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
918 if ((enclosingMethod != null) && !enclosingMethod.isCtor()){
919 return createMethodObject(env, mci, enclosingMethod);
925 public boolean isAnonymousClass____Z (MJIEnv env, int robj){
926 ClassInfo ci = env.getReferredClassInfo(robj);
928 if (ci.getName().contains("$")){
929 cname = ci.getName().substring(ci.getName().lastIndexOf('$') + 1);
931 return (cname == null) ? false : cname.matches("\\d+?");
935 public boolean isEnum____Z (MJIEnv env, int robj){
936 ClassInfo ci = env.getReferredClassInfo(robj);
940 // Similar to getEnclosingClass() except it returns null for the case of
943 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef){
944 ClassInfo ci = env.getReferredClassInfo(clsRef);
945 if (isLocalOrAnonymousClass(ci)){
948 return getEnclosingClass____Ljava_lang_Class_2(env, clsRef);
953 public boolean isLocalClass____Z (MJIEnv env, int robj){
954 ClassInfo ci = env.getReferredClassInfo(robj);
955 return isLocalOrAnonymousClass(ci) && !isAnonymousClass____Z(env, robj);
958 private boolean isLocalOrAnonymousClass (ClassInfo ci){
959 return (ci.getEnclosingMethodInfo() != null);
963 public boolean isMemberClass____Z (MJIEnv env, int robj){
964 ClassInfo ci = env.getReferredClassInfo(robj);
965 return (ci.getEnclosingClassInfo() != null) && !isLocalOrAnonymousClass(ci);
969 * Append the package name prefix of the class represented by robj, if the name is not
970 * absolute. OW, remove leading "/".
973 public int getResolvedName__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int robj, int resRef){
974 String rname = env.getStringObject(resRef);
975 ClassInfo ci = env.getReferredClassInfo(robj);
979 if (!rname.startsWith("/")) {
981 while (c.isArray()) {
982 c = c.getComponentClassInfo();
984 String baseName = c.getName();
985 int index = baseName.lastIndexOf('.');
987 rname = baseName.substring(0, index).replace('.', '/')
991 rname = rname.substring(1);
994 return env.newString(rname);