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";
37 // TODO: Fix for Groovy's model-checking
38 static final String TYPEVARIABLE_CLASSNAME = "java.lang.reflect.TypeVariable";
40 public static boolean init (Config conf){
41 // we create Method and Constructor objects, so we better make sure these
42 // classes are initialized (they already might be)
43 JPF_java_lang_reflect_Method.init(conf);
44 JPF_java_lang_reflect_Constructor.init(conf);
49 public boolean isArray____Z (MJIEnv env, int robj) {
50 ClassInfo ci = env.getReferredClassInfo( robj);
55 public int getComponentType____Ljava_lang_Class_2 (MJIEnv env, int robj) {
56 if (isArray____Z(env, robj)) {
57 ThreadInfo ti = env.getThreadInfo();
58 Instruction insn = ti.getPC();
59 ClassInfo ci = env.getReferredClassInfo( robj).getComponentClassInfo();
61 if (ci.initializeClass(ti)){
62 env.repeatInvocation();
66 return ci.getClassObjectRef();
73 public boolean isInstance__Ljava_lang_Object_2__Z (MJIEnv env, int robj,
75 ElementInfo sei = env.getStaticElementInfo(robj);
76 ClassInfo ci = sei.getClassInfo();
77 ClassInfo ciOther = env.getClassInfo(r1);
78 return (ciOther.isInstanceOf(ci));
82 public boolean isInterface____Z (MJIEnv env, int robj){
83 ClassInfo ci = env.getReferredClassInfo( robj);
84 return ci.isInterface();
88 public boolean isAssignableFrom__Ljava_lang_Class_2__Z (MJIEnv env, int rcls,
90 ElementInfo sei1 = env.getStaticElementInfo(rcls);
91 ClassInfo ci1 = sei1.getClassInfo();
93 ElementInfo sei2 = env.getStaticElementInfo(r1);
94 ClassInfo ci2 = sei2.getClassInfo();
96 return ci2.isInstanceOf( ci1);
100 public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
101 ClassInfo ci = env.getReferredClassInfo( robj);
102 AnnotationInfo[] ai = ci.getAnnotations();
105 return env.newAnnotationProxies(ai);
106 } catch (ClinitRequired x){
107 env.handleClinitRequest(x.getRequiredClassInfo());
112 // TODO: Fix for Groovy's model-checking
113 // TODO: THIS NEEDS TO BE SUBSTITUTED BY THE PROPER METHODS! VERY DIRTY RIGHT NOW!
115 public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int robj){
116 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
117 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
118 //ClassInfo rci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.Test");
119 // TODO: Need to 1) Just create the object of TypeVariableImpl, 2) Declare class type and name only, 3) Return the
120 // object reference back to the caller
121 int tvRef = env.newObject(ci);
122 ElementInfo ei = env.getModifiableElementInfo(tvRef);
124 ClassInfo tci = env.getReferredClassInfo( robj);
125 //ei.setReferenceField("genericDeclaration", env.newObject(tci.getName() + ".class"));
126 ei.setReferenceField("name", env.newString("TUVW"));
127 int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 1);
128 for (int i = 0; i < 1; i++) {
129 env.setReferenceArrayElement(aRef, i, tvRef);
136 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj,
138 ClassInfo ci = env.getReferredClassInfo( robj);
139 ClassInfo aci = env.getReferredClassInfo(annoClsRef);
141 AnnotationInfo ai = ci.getAnnotation(aci.getName());
143 ClassInfo aciProxy = aci.getAnnotationProxy();
146 return env.newAnnotationProxy(aciProxy, ai);
147 } catch (ClinitRequired x){
148 env.handleClinitRequest(x.getRequiredClassInfo());
157 public int getPrimitiveClass__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
158 int rcls, int stringRef) {
159 // we don't really have to check for a valid class name here, since
160 // this is a package default method that just gets called from
161 // the clinit of box classes
162 // note this does NOT return the box class (e.g. java.lang.Integer), which
163 // is a normal, functional class, but a primitive class (e.g. 'int') that
164 // is rather a strange beast (not even Object derived)
166 ClassLoaderInfo scli = env.getSystemClassLoaderInfo(); // this is the one responsible for builtin classes
167 String primClsName = env.getStringObject(stringRef); // always initialized
169 ClassInfo ci = scli.getResolvedClassInfo(primClsName);
170 return ci.getClassObjectRef();
174 public boolean desiredAssertionStatus____Z (MJIEnv env, int robj) {
175 ClassInfo ci = env.getReferredClassInfo(robj);
176 return ci.desiredAssertionStatus();
179 public static int getClassObject (MJIEnv env, ClassInfo ci){
180 ThreadInfo ti = env.getThreadInfo();
181 Instruction insn = ti.getPC();
183 if (ci.initializeClass(ti)){
184 env.repeatInvocation();
188 StaticElementInfo ei = ci.getStaticElementInfo();
189 int ref = ei.getClassObjectRef();
195 public int forName__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
198 if (clsNameRef == MJIEnv.NULL){
199 env.throwException("java.lang.NullPointerException", "no class name provided");
203 String clsName = env.getStringObject(clsNameRef);
205 if (clsName.isEmpty()){
206 env.throwException("java.lang.ClassNotFoundException", "empty class name");
210 ThreadInfo ti = env.getThreadInfo();
211 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
212 // class of the method that includes the invocation of Class.forName()
213 ClassInfo cls = mi.getClassInfo();
216 // for array type, the component terminal must be resolved
217 if(clsName.charAt(0)=='[') {
218 name = Types.getComponentTerminal(clsName);
223 // make the classloader of the class including the invocation of
224 // Class.forName() resolve the class with the given name
226 cls.resolveReferencedClass(name);
227 } catch(LoadOnJPFRequired lre) {
228 env.repeatInvocation();
232 // The class obtained here is the same as the resolved one, except
233 // if it represents an array type
234 ClassInfo ci = cls.getClassLoaderInfo().getResolvedClassInfo(clsName);
236 return getClassObject(env, ci);
240 * this is an example of a native method issuing direct calls - otherwise known
242 * We don't have to deal with class init here anymore, since this is called
243 * via the class object of the class to instantiate
246 public int newInstance____Ljava_lang_Object_2 (MJIEnv env, int robj) {
247 ThreadInfo ti = env.getThreadInfo();
248 DirectCallStackFrame frame = ti.getReturnedDirectCall();
250 ClassInfo ci = env.getReferredClassInfo(robj); // what are we
251 MethodInfo miCtor = ci.getMethod("<init>()V", true); // note there always is one since something needs to call Object()
253 if (frame == null){ // first time around
254 if(ci.isAbstract()){ // not allowed to instantiate
255 env.throwException("java.lang.InstantiationException");
259 // <2do> - still need to handle protected
260 if (miCtor.isPrivate()) {
261 env.throwException("java.lang.IllegalAccessException", "cannot access non-public member of class " + ci.getName());
265 int objRef = env.newObjectOfUncheckedClass(ci); // create the thing
267 frame = miCtor.createDirectCallStackFrame(ti, 1);
268 // note that we don't set this as a reflection call since it is supposed to propagate exceptions
269 frame.setReferenceArgument(0, objRef, null);
270 frame.setLocalReferenceVariable(0, objRef); // (1) store ref for retrieval during re-exec
273 // check if we have to push clinits
274 ci.initializeClass(ti);
276 env.repeatInvocation();
279 } else { // re-execution
280 int objRef = frame.getLocalVariable(0); // that's the object ref we set in (1)
286 public int getSuperclass____Ljava_lang_Class_2 (MJIEnv env, int robj) {
287 ClassInfo ci = env.getReferredClassInfo( robj);
288 ClassInfo sci = ci.getSuperClass();
290 return sci.getClassObjectRef();
296 int getMethod (MJIEnv env, int clsRef, ClassInfo ciMethod, String mname, int argTypesRef,
297 boolean isRecursiveLookup, boolean publicOnly) {
299 ClassInfo ci = env.getReferredClassInfo( clsRef);
301 StringBuilder sb = new StringBuilder(mname);
303 int nParams = argTypesRef != MJIEnv.NULL ? env.getArrayLength(argTypesRef) : 0;
304 for (int i=0; i<nParams; i++) {
305 int cRef = env.getReferenceArrayElement(argTypesRef, i);
306 ClassInfo cit = env.getReferredClassInfo( cRef);
307 String tname = cit.getName();
308 String tcode = tname;
309 tcode = Types.getTypeSignature(tcode, false);
313 String fullMthName = sb.toString();
315 MethodInfo mi = ci.getReflectionMethod(fullMthName, isRecursiveLookup);
316 if (mi == null || (publicOnly && !mi.isPublic())) {
317 env.throwException("java.lang.NoSuchMethodException", ci.getName() + '.' + fullMthName);
321 return createMethodObject(env, ciMethod, mi);
325 int createMethodObject (MJIEnv env, ClassInfo objectCi, MethodInfo mi) {
326 // NOTE - we rely on Constructor and Method peers being initialized
328 return JPF_java_lang_reflect_Constructor.createConstructorObject(env, objectCi, mi);
330 return JPF_java_lang_reflect_Method.createMethodObject(env, objectCi, mi);
335 public int getDeclaredMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
336 int nameRef, int argTypesRef) {
337 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
339 env.repeatInvocation();
343 String mname = env.getStringObject(nameRef);
344 return getMethod(env, clsRef, mci, mname, argTypesRef, false, false);
348 public int getDeclaredConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env,
351 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
353 env.repeatInvocation();
357 int ctorRef = getMethod(env,clsRef, mci, "<init>",argTypesRef,false, false);
362 public int getMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
363 int nameRef, int argTypesRef) {
364 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
366 env.repeatInvocation();
370 String mname = env.getStringObject(nameRef);
371 return getMethod( env, clsRef, mci, mname, argTypesRef, true, true);
374 private void addDeclaredMethodsRec (boolean includeSuperClasses, HashMap<String,MethodInfo>methods, ClassInfo ci){
376 if (includeSuperClasses){ // do NOT include Object methods for interfaces
377 ClassInfo sci = ci.getSuperClass();
379 addDeclaredMethodsRec( includeSuperClasses, methods,sci);
383 ClassLoaderInfo cl = ci.getClassLoaderInfo();
384 for (String ifcName : ci.getDirectInterfaceNames()){
385 ClassInfo ici = cl.getResolvedClassInfo(ifcName); // has to be already defined, so no exception
386 addDeclaredMethodsRec( includeSuperClasses, methods,ici);
389 for (MethodInfo mi : ci.getDeclaredMethodInfos()) {
390 // filter out non-public, <clinit> and <init>
391 if (mi.isPublic() && (mi.getName().charAt(0) != '<')) {
392 String mname = mi.getUniqueName();
394 if (!(ci.isInterface() && methods.containsKey(mname))){
395 methods.put(mname, mi);
402 public int getMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
403 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
405 env.repeatInvocation();
409 ClassInfo ci = env.getReferredClassInfo(objref);
411 // collect all the public, non-ctor instance methods
412 if (!ci.isPrimitive()) {
413 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
414 addDeclaredMethodsRec( !ci.isInterface(), methods,ci);
416 int n = methods.size();
417 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", n);
420 for (MethodInfo mi : methods.values()){
421 int mref = createMethodObject(env, mci, mi);
422 env.setReferenceArrayElement(aref,i++,mref);
428 return env.newObjectArray("Ljava/lang/reflect/Method;", 0);
433 public int getDeclaredMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
434 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
436 env.repeatInvocation();
440 ClassInfo ci = env.getReferredClassInfo(objref);
441 MethodInfo[] methodInfos = ci.getDeclaredMethodInfos();
443 // we have to filter out the ctors and the static init
444 int nMth = methodInfos.length;
445 for (int i=0; i<methodInfos.length; i++){
446 if (methodInfos[i].getName().charAt(0) == '<'){
447 methodInfos[i] = null;
452 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", nMth);
454 for (int i=0, j=0; i<methodInfos.length; i++) {
455 if (methodInfos[i] != null){
456 int mref = createMethodObject(env, mci, methodInfos[i]);
457 env.setReferenceArrayElement(aref,j++,mref);
464 int getConstructors (MJIEnv env, int objref, boolean publicOnly){
465 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
467 env.repeatInvocation();
471 ClassInfo ci = env.getReferredClassInfo(objref);
472 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
474 // we have to filter out the ctors and the static init
475 for (MethodInfo mi : ci.getDeclaredMethodInfos()){
476 if (mi.getName().equals("<init>")){
477 if (!publicOnly || mi.isPublic()) {
483 int nCtors = ctors.size();
484 int aref = env.newObjectArray("Ljava/lang/reflect/Constructor;", nCtors);
486 for (int i=0; i<nCtors; i++){
487 env.setReferenceArrayElement(aref, i, createMethodObject(env, mci, ctors.get(i)));
494 public int getConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
495 return getConstructors(env, objref, true);
499 public int getDeclaredConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
500 return getConstructors(env, objref, false);
504 public int getConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env, int clsRef,
506 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
508 env.repeatInvocation();
512 // <2do> should only return a public ctor
513 return getMethod(env,clsRef, mci, "<init>",argTypesRef,false,true);
516 // this is only used for system classes such as java.lang.reflect.Method
517 ClassInfo getInitializedClassInfo (MJIEnv env, String clsName){
518 ThreadInfo ti = env.getThreadInfo();
519 Instruction insn = ti.getPC();
520 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo( clsName);
522 if (ci.initializeClass(ti)){
530 public void initialize0____V (MJIEnv env, int clsObjRef){
531 ClassInfo ci = env.getReferredClassInfo( clsObjRef);
532 ci.initializeClass(ThreadInfo.currentThread);
535 Set<ClassInfo> getInitializedInterfaces (MJIEnv env, ClassInfo ci){
536 ThreadInfo ti = env.getThreadInfo();
537 Instruction insn = ti.getPC();
539 Set<ClassInfo> ifcs = ci.getAllInterfaceClassInfos();
540 for (ClassInfo ciIfc : ifcs){
541 if (ciIfc.initializeClass(ti)){
549 static int createFieldObject (MJIEnv env, FieldInfo fi, ClassInfo fci){
550 int regIdx = JPF_java_lang_reflect_Field.registerFieldInfo(fi);
552 int eidx = env.newObject(fci);
553 ElementInfo ei = env.getModifiableElementInfo(eidx);
554 ei.setIntField("regIdx", regIdx);
560 public int getDeclaredFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int objRef) {
561 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
563 env.repeatInvocation();
567 ClassInfo ci = env.getReferredClassInfo(objRef);
568 int nInstance = ci.getNumberOfDeclaredInstanceFields();
569 int nStatic = ci.getNumberOfStaticFields();
570 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", nInstance + nStatic);
573 for (i=0; i<nStatic; i++) {
574 FieldInfo fi = ci.getStaticField(i);
575 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
578 for (i=0; i<nInstance; i++) {
579 FieldInfo fi = ci.getDeclaredInstanceField(i);
580 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
587 public int getFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef){
588 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
590 env.repeatInvocation();
594 ClassInfo ci = env.getReferredClassInfo(clsRef);
595 // interfaces might not be initialized yet, so we have to check first
596 Set<ClassInfo> ifcs = getInitializedInterfaces( env, ci);
598 env.repeatInvocation();
602 ArrayList<FieldInfo> fiList = new ArrayList<FieldInfo>();
603 for (; ci != null; ci = ci.getSuperClass()){
604 // the host VM returns them in order of declaration, but the spec says there is no guaranteed order so we keep it simple
605 for (FieldInfo fi : ci.getDeclaredInstanceFields()){
610 for (FieldInfo fi : ci.getDeclaredStaticFields()){
617 for (ClassInfo ciIfc : ifcs){
618 for (FieldInfo fi : ciIfc.getDeclaredStaticFields()){
619 fiList.add(fi); // there are no non-public fields in interfaces
623 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", fiList.size());
625 for (FieldInfo fi : fiList){
626 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
632 int getField (MJIEnv env, int clsRef, int nameRef, boolean isRecursiveLookup) {
633 ClassInfo ci = env.getReferredClassInfo( clsRef);
634 String fname = env.getStringObject(nameRef);
637 if (isRecursiveLookup) {
638 fi = ci.getInstanceField(fname);
640 fi = ci.getStaticField(fname);
643 fi = ci.getDeclaredInstanceField(fname);
645 fi = ci.getDeclaredStaticField(fname);
650 env.throwException("java.lang.NoSuchFieldException", fname);
654 // don't do a Field clinit before we know there is such a field
655 ClassInfo fci = getInitializedClassInfo( env, FIELD_CLASSNAME);
657 env.repeatInvocation();
661 return createFieldObject( env, fi, fci);
666 public int getDeclaredField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
667 return getField(env,clsRef,nameRef, false);
671 public int getField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
672 return getField(env,clsRef,nameRef, true);
676 public int getModifiers____I (MJIEnv env, int clsRef){
677 ClassInfo ci = env.getReferredClassInfo(clsRef);
678 return ci.getModifiers();
682 public int getEnumConstants_____3Ljava_lang_Object_2 (MJIEnv env, int clsRef){
683 ClassInfo ci = env.getReferredClassInfo(clsRef);
685 if (env.requiresClinitExecution(ci)){
686 env.repeatInvocation();
690 if (ci.getSuperClass().getName().equals("java.lang.Enum")) {
691 ArrayList<FieldInfo> list = new ArrayList<FieldInfo>();
692 String cName = ci.getName();
694 for (FieldInfo fi : ci.getDeclaredStaticFields()) {
695 if (fi.isFinal() && cName.equals(fi.getType())){
700 int aRef = env.newObjectArray(cName, list.size());
701 StaticElementInfo sei = ci.getStaticElementInfo();
703 for (FieldInfo fi : list){
704 env.setReferenceArrayElement( aRef, i++, sei.getReferenceField(fi));
713 public int getInterfaces_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
714 ClassInfo ci = env.getReferredClassInfo(clsRef);
715 int aref = MJIEnv.NULL;
716 ThreadInfo ti = env.getThreadInfo();
718 // contrary to the API doc, this only returns the interfaces directly
719 // implemented by this class, not it's bases
720 // <2do> this is not exactly correct, since the interfaces should be ordered
721 Set<ClassInfo> interfaces = ci.getInterfaceClassInfos();
722 aref = env.newObjectArray("Ljava/lang/Class;", interfaces.size());
725 for (ClassInfo ifc: interfaces){
726 env.setReferenceArrayElement(aref, i++, ifc.getClassObjectRef());
734 * <2do> needs to load from the classfile location, NOT the MJIEnv (native) class
736 * @author Sebastian Gfeller (sebastian.gfeller@gmail.com)
737 * @author Tihomir Gvero (tihomir.gvero@gmail.com)
740 public int getByteArrayFromResourceStream__Ljava_lang_String_2___3B(MJIEnv env, int clsRef, int nameRef) {
741 String name = env.getStringObject(nameRef);
743 // <2do> this is not loading from the classfile location! fix it
744 InputStream is = env.getClass().getResourceAsStream(name);
748 // We assume that the entire input stream can be read at the moment,
749 // although this could break.
750 byte[] content = null;
752 content = new byte[is.available()];
754 } catch (IOException e) {
755 throw new RuntimeException(e);
757 // Now if everything worked, the content should be in the byte buffer.
758 // We put this buffer into the JPF VM.
759 return env.newByteArray(content);
763 public int getEnclosingClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef) {
764 ClassInfo ciEncl = env.getReferredClassInfo( clsRef).getEnclosingClassInfo();
770 if (ciEncl.initializeClass(env.getThreadInfo())) {
771 env.repeatInvocation();
775 return ciEncl.getClassObjectRef();
779 public int getDeclaredClasses_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
780 ClassInfo ci = env.getReferredClassInfo(clsRef);
781 String[] innerClassNames = ci.getInnerClasses();
782 int aref = MJIEnv.NULL;
783 ThreadInfo ti = env.getThreadInfo();
785 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
786 // class of the method that includes the invocation of Class.getDeclaredClasses
787 ClassInfo cls = mi.getClassInfo();
789 // first resolve all the inner classes
790 int length = innerClassNames.length;
791 ClassInfo[] resolvedInnerClass = new ClassInfo[length];
792 for(int i=0; i<length; i++) {
794 resolvedInnerClass[i] = cls.resolveReferencedClass(innerClassNames[i]);
795 } catch(LoadOnJPFRequired lre) {
796 env.repeatInvocation();
801 aref = env.newObjectArray("Ljava/lang/Class;", innerClassNames.length);
802 for (int i=0; i<length; i++){
803 ClassInfo ici = resolvedInnerClass[i];
804 if (!ici.isRegistered()) {
805 ici.registerClass(ti);
807 env.setReferenceArrayElement(aref, i, ici.getClassObjectRef());
813 private String getCanonicalName (ClassInfo ci){
815 String canonicalName = getCanonicalName(ci.getComponentClassInfo());
816 if (canonicalName != null){
817 return canonicalName + "[]";
822 if (isLocalOrAnonymousClass(ci)) {
825 if (ci.getEnclosingClassInfo() == null){
828 String enclosingName = getCanonicalName(ci.getEnclosingClassInfo());
829 if (enclosingName == null){ return null; }
830 return enclosingName + "." + ci.getSimpleName();
835 public int getCanonicalName____Ljava_lang_String_2 (MJIEnv env, int clsRef){
836 ClassInfo ci = env.getReferredClassInfo(clsRef);
837 return env.newString(getCanonicalName(ci));
841 public boolean isAnnotation____Z (MJIEnv env, int clsObjRef){
842 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
843 return (ci.getModifiers() & 0x2000) != 0;
847 public boolean isAnnotationPresent__Ljava_lang_Class_2__Z (MJIEnv env, int clsObjRef, int annoClsObjRef){
848 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
849 ClassInfo ciAnno = env.getReferredClassInfo(annoClsObjRef);
851 return ci.getAnnotation( ciAnno.getName()) != null;
855 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
856 ClassInfo ci = env.getReferredClassInfo(robj);
859 return env.newAnnotationProxies(ci.getDeclaredAnnotations());
860 } catch (ClinitRequired x){
861 env.handleClinitRequest(x.getRequiredClassInfo());
867 public int getEnclosingConstructor____Ljava_lang_reflect_Constructor_2 (MJIEnv env, int robj){
868 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
870 env.repeatInvocation();
873 ClassInfo ci = env.getReferredClassInfo(robj);
874 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
876 if ((enclosingMethod != null) && enclosingMethod.isCtor()){
877 return createMethodObject(env, mci, enclosingMethod);
883 public int getEnclosingMethod____Ljava_lang_reflect_Method_2 (MJIEnv env, int robj){
884 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
886 env.repeatInvocation();
889 ClassInfo ci = env.getReferredClassInfo(robj);
890 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
892 if ((enclosingMethod != null) && !enclosingMethod.isCtor()){
893 return createMethodObject(env, mci, enclosingMethod);
899 public boolean isAnonymousClass____Z (MJIEnv env, int robj){
900 ClassInfo ci = env.getReferredClassInfo(robj);
902 if (ci.getName().contains("$")){
903 cname = ci.getName().substring(ci.getName().lastIndexOf('$') + 1);
905 return (cname == null) ? false : cname.matches("\\d+?");
909 public boolean isEnum____Z (MJIEnv env, int robj){
910 ClassInfo ci = env.getReferredClassInfo(robj);
914 // Similar to getEnclosingClass() except it returns null for the case of
917 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef){
918 ClassInfo ci = env.getReferredClassInfo(clsRef);
919 if (isLocalOrAnonymousClass(ci)){
922 return getEnclosingClass____Ljava_lang_Class_2(env, clsRef);
927 public boolean isLocalClass____Z (MJIEnv env, int robj){
928 ClassInfo ci = env.getReferredClassInfo(robj);
929 return isLocalOrAnonymousClass(ci) && !isAnonymousClass____Z(env, robj);
932 private boolean isLocalOrAnonymousClass (ClassInfo ci){
933 return (ci.getEnclosingMethodInfo() != null);
937 public boolean isMemberClass____Z (MJIEnv env, int robj){
938 ClassInfo ci = env.getReferredClassInfo(robj);
939 return (ci.getEnclosingClassInfo() != null) && !isLocalOrAnonymousClass(ci);
943 * Append the package name prefix of the class represented by robj, if the name is not
944 * absolute. OW, remove leading "/".
947 public int getResolvedName__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int robj, int resRef){
948 String rname = env.getStringObject(resRef);
949 ClassInfo ci = env.getReferredClassInfo(robj);
953 if (!rname.startsWith("/")) {
955 while (c.isArray()) {
956 c = c.getComponentClassInfo();
958 String baseName = c.getName();
959 int index = baseName.lastIndexOf('.');
961 rname = baseName.substring(0, index).replace('.', '/')
965 rname = rname.substring(1);
968 return env.newString(rname);