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
112 public int getTypeParameters_____3Ljava_lang_reflect_TypeVariable_2 (MJIEnv env, int robj){
113 // Get the ClassInfo for this class
114 ClassInfo tci = env.getReferredClassInfo(robj);
115 String[] typeVars = tci.getGenericTypeVariableNames();
117 // Return with null if this is not a generic class
118 if (typeVars.length == 0) {
119 int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", 0);
122 // Now create a TypeVariableImpl object for every type variable name; get the ClassInfo for TypeVariableImpl
123 ClassLoaderInfo cli = env.getSystemClassLoaderInfo();
124 ClassInfo ci = cli.getResolvedClassInfo("sun.reflect.generics.reflectiveObjects.TypeVariableImpl");
125 int[] var = new int[typeVars.length];
127 for(int i = 0; i < typeVars.length; i++) {
128 int typeVarRef = env.newObject(ci);
129 ElementInfo ei = env.getModifiableElementInfo(typeVarRef);
130 ei.setReferenceField("genericDeclaration", tci.getClassObjectRef());
131 ei.setReferenceField("name", env.newString(typeVars[i]));
134 int aRef = env.newObjectArray("Ljava/lang/reflect/TypeVariable;", typeVars.length);
136 // Set references for every array element
137 for (int i = 0; i < typeVars.length; i++) {
138 env.setReferenceArrayElement(aRef, i, var[i]);
145 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj,
147 ClassInfo ci = env.getReferredClassInfo( robj);
148 ClassInfo aci = env.getReferredClassInfo(annoClsRef);
150 AnnotationInfo ai = ci.getAnnotation(aci.getName());
152 ClassInfo aciProxy = aci.getAnnotationProxy();
155 return env.newAnnotationProxy(aciProxy, ai);
156 } catch (ClinitRequired x){
157 env.handleClinitRequest(x.getRequiredClassInfo());
166 public int getPrimitiveClass__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
167 int rcls, int stringRef) {
168 // we don't really have to check for a valid class name here, since
169 // this is a package default method that just gets called from
170 // the clinit of box classes
171 // note this does NOT return the box class (e.g. java.lang.Integer), which
172 // is a normal, functional class, but a primitive class (e.g. 'int') that
173 // is rather a strange beast (not even Object derived)
175 ClassLoaderInfo scli = env.getSystemClassLoaderInfo(); // this is the one responsible for builtin classes
176 String primClsName = env.getStringObject(stringRef); // always initialized
178 ClassInfo ci = scli.getResolvedClassInfo(primClsName);
179 return ci.getClassObjectRef();
183 public boolean desiredAssertionStatus____Z (MJIEnv env, int robj) {
184 ClassInfo ci = env.getReferredClassInfo(robj);
185 return ci.desiredAssertionStatus();
188 public static int getClassObject (MJIEnv env, ClassInfo ci){
189 ThreadInfo ti = env.getThreadInfo();
190 Instruction insn = ti.getPC();
192 if (ci.initializeClass(ti)){
193 env.repeatInvocation();
197 StaticElementInfo ei = ci.getStaticElementInfo();
198 int ref = ei.getClassObjectRef();
204 public int forName__Ljava_lang_String_2__Ljava_lang_Class_2 (MJIEnv env,
207 if (clsNameRef == MJIEnv.NULL){
208 env.throwException("java.lang.NullPointerException", "no class name provided");
212 String clsName = env.getStringObject(clsNameRef);
214 if (clsName.isEmpty()){
215 env.throwException("java.lang.ClassNotFoundException", "empty class name");
219 ThreadInfo ti = env.getThreadInfo();
220 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
221 // class of the method that includes the invocation of Class.forName()
222 ClassInfo cls = mi.getClassInfo();
225 // for array type, the component terminal must be resolved
226 if(clsName.charAt(0)=='[') {
227 name = Types.getComponentTerminal(clsName);
232 // make the classloader of the class including the invocation of
233 // Class.forName() resolve the class with the given name
235 cls.resolveReferencedClass(name);
236 } catch(LoadOnJPFRequired lre) {
237 env.repeatInvocation();
241 // The class obtained here is the same as the resolved one, except
242 // if it represents an array type
243 ClassInfo ci = cls.getClassLoaderInfo().getResolvedClassInfo(clsName);
245 return getClassObject(env, ci);
249 * this is an example of a native method issuing direct calls - otherwise known
251 * We don't have to deal with class init here anymore, since this is called
252 * via the class object of the class to instantiate
255 public int newInstance____Ljava_lang_Object_2 (MJIEnv env, int robj) {
256 ThreadInfo ti = env.getThreadInfo();
257 DirectCallStackFrame frame = ti.getReturnedDirectCall();
259 ClassInfo ci = env.getReferredClassInfo(robj); // what are we
260 MethodInfo miCtor = ci.getMethod("<init>()V", true); // note there always is one since something needs to call Object()
262 if (frame == null){ // first time around
263 if(ci.isAbstract()){ // not allowed to instantiate
264 env.throwException("java.lang.InstantiationException");
268 // <2do> - still need to handle protected
269 if (miCtor.isPrivate()) {
270 env.throwException("java.lang.IllegalAccessException", "cannot access non-public member of class " + ci.getName());
274 int objRef = env.newObjectOfUncheckedClass(ci); // create the thing
276 frame = miCtor.createDirectCallStackFrame(ti, 1);
277 // note that we don't set this as a reflection call since it is supposed to propagate exceptions
278 frame.setReferenceArgument(0, objRef, null);
279 frame.setLocalReferenceVariable(0, objRef); // (1) store ref for retrieval during re-exec
282 // check if we have to push clinits
283 ci.initializeClass(ti);
285 env.repeatInvocation();
288 } else { // re-execution
289 int objRef = frame.getLocalVariable(0); // that's the object ref we set in (1)
295 public int getSuperclass____Ljava_lang_Class_2 (MJIEnv env, int robj) {
296 ClassInfo ci = env.getReferredClassInfo( robj);
297 ClassInfo sci = ci.getSuperClass();
299 return sci.getClassObjectRef();
305 int getMethod (MJIEnv env, int clsRef, ClassInfo ciMethod, String mname, int argTypesRef,
306 boolean isRecursiveLookup, boolean publicOnly) {
308 ClassInfo ci = env.getReferredClassInfo( clsRef);
310 StringBuilder sb = new StringBuilder(mname);
312 int nParams = argTypesRef != MJIEnv.NULL ? env.getArrayLength(argTypesRef) : 0;
313 for (int i=0; i<nParams; i++) {
314 int cRef = env.getReferenceArrayElement(argTypesRef, i);
315 ClassInfo cit = env.getReferredClassInfo( cRef);
316 String tname = cit.getName();
317 String tcode = tname;
318 tcode = Types.getTypeSignature(tcode, false);
322 String fullMthName = sb.toString();
324 MethodInfo mi = ci.getReflectionMethod(fullMthName, isRecursiveLookup);
325 if (mi == null || (publicOnly && !mi.isPublic())) {
326 env.throwException("java.lang.NoSuchMethodException", ci.getName() + '.' + fullMthName);
330 return createMethodObject(env, ciMethod, mi);
334 int createMethodObject (MJIEnv env, ClassInfo objectCi, MethodInfo mi) {
335 // NOTE - we rely on Constructor and Method peers being initialized
337 return JPF_java_lang_reflect_Constructor.createConstructorObject(env, objectCi, mi);
339 return JPF_java_lang_reflect_Method.createMethodObject(env, objectCi, mi);
344 public int getDeclaredMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
345 int nameRef, int argTypesRef) {
346 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
348 env.repeatInvocation();
352 String mname = env.getStringObject(nameRef);
353 return getMethod(env, clsRef, mci, mname, argTypesRef, false, false);
357 public int getDeclaredConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env,
360 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
362 env.repeatInvocation();
366 int ctorRef = getMethod(env,clsRef, mci, "<init>",argTypesRef,false, false);
371 public int getMethod__Ljava_lang_String_2_3Ljava_lang_Class_2__Ljava_lang_reflect_Method_2 (MJIEnv env, int clsRef,
372 int nameRef, int argTypesRef) {
373 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
375 env.repeatInvocation();
379 String mname = env.getStringObject(nameRef);
380 return getMethod( env, clsRef, mci, mname, argTypesRef, true, true);
383 private void addDeclaredMethodsRec (boolean includeSuperClasses, HashMap<String,MethodInfo>methods, ClassInfo ci){
385 if (includeSuperClasses){ // do NOT include Object methods for interfaces
386 ClassInfo sci = ci.getSuperClass();
388 addDeclaredMethodsRec( includeSuperClasses, methods,sci);
392 ClassLoaderInfo cl = ci.getClassLoaderInfo();
393 for (String ifcName : ci.getDirectInterfaceNames()){
394 ClassInfo ici = cl.getResolvedClassInfo(ifcName); // has to be already defined, so no exception
395 addDeclaredMethodsRec( includeSuperClasses, methods,ici);
398 for (MethodInfo mi : ci.getDeclaredMethodInfos()) {
399 // filter out non-public, <clinit> and <init>
400 if (mi.isPublic() && (mi.getName().charAt(0) != '<')) {
401 String mname = mi.getUniqueName();
403 if (!(ci.isInterface() && methods.containsKey(mname))){
404 methods.put(mname, mi);
411 public int getMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
412 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
414 env.repeatInvocation();
418 ClassInfo ci = env.getReferredClassInfo(objref);
420 // collect all the public, non-ctor instance methods
421 if (!ci.isPrimitive()) {
422 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
423 addDeclaredMethodsRec( !ci.isInterface(), methods,ci);
425 int n = methods.size();
426 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", n);
429 for (MethodInfo mi : methods.values()){
430 int mref = createMethodObject(env, mci, mi);
431 env.setReferenceArrayElement(aref,i++,mref);
437 return env.newObjectArray("Ljava/lang/reflect/Method;", 0);
442 public int getDeclaredMethods_____3Ljava_lang_reflect_Method_2 (MJIEnv env, int objref) {
443 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
445 env.repeatInvocation();
449 ClassInfo ci = env.getReferredClassInfo(objref);
450 MethodInfo[] methodInfos = ci.getDeclaredMethodInfos();
452 // we have to filter out the ctors and the static init
453 int nMth = methodInfos.length;
454 for (int i=0; i<methodInfos.length; i++){
455 if (methodInfos[i].getName().charAt(0) == '<'){
456 methodInfos[i] = null;
461 int aref = env.newObjectArray("Ljava/lang/reflect/Method;", nMth);
463 for (int i=0, j=0; i<methodInfos.length; i++) {
464 if (methodInfos[i] != null){
465 int mref = createMethodObject(env, mci, methodInfos[i]);
466 env.setReferenceArrayElement(aref,j++,mref);
473 int getConstructors (MJIEnv env, int objref, boolean publicOnly){
474 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
476 env.repeatInvocation();
480 ClassInfo ci = env.getReferredClassInfo(objref);
481 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
483 // we have to filter out the ctors and the static init
484 for (MethodInfo mi : ci.getDeclaredMethodInfos()){
485 if (mi.getName().equals("<init>")){
486 if (!publicOnly || mi.isPublic()) {
492 int nCtors = ctors.size();
493 int aref = env.newObjectArray("Ljava/lang/reflect/Constructor;", nCtors);
495 for (int i=0; i<nCtors; i++){
496 env.setReferenceArrayElement(aref, i, createMethodObject(env, mci, ctors.get(i)));
503 public int getConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
504 return getConstructors(env, objref, true);
508 public int getDeclaredConstructors_____3Ljava_lang_reflect_Constructor_2 (MJIEnv env, int objref){
509 return getConstructors(env, objref, false);
513 public int getConstructor___3Ljava_lang_Class_2__Ljava_lang_reflect_Constructor_2 (MJIEnv env, int clsRef,
515 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
517 env.repeatInvocation();
521 // <2do> should only return a public ctor
522 return getMethod(env,clsRef, mci, "<init>",argTypesRef,false,true);
525 // this is only used for system classes such as java.lang.reflect.Method
526 ClassInfo getInitializedClassInfo (MJIEnv env, String clsName){
527 ThreadInfo ti = env.getThreadInfo();
528 Instruction insn = ti.getPC();
529 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo( clsName);
531 if (ci.initializeClass(ti)){
539 public void initialize0____V (MJIEnv env, int clsObjRef){
540 ClassInfo ci = env.getReferredClassInfo( clsObjRef);
541 ci.initializeClass(ThreadInfo.currentThread);
544 Set<ClassInfo> getInitializedInterfaces (MJIEnv env, ClassInfo ci){
545 ThreadInfo ti = env.getThreadInfo();
546 Instruction insn = ti.getPC();
548 Set<ClassInfo> ifcs = ci.getAllInterfaceClassInfos();
549 for (ClassInfo ciIfc : ifcs){
550 if (ciIfc.initializeClass(ti)){
558 static int createFieldObject (MJIEnv env, FieldInfo fi, ClassInfo fci){
559 int regIdx = JPF_java_lang_reflect_Field.registerFieldInfo(fi);
561 int eidx = env.newObject(fci);
562 ElementInfo ei = env.getModifiableElementInfo(eidx);
563 ei.setIntField("regIdx", regIdx);
569 public int getDeclaredFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int objRef) {
570 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
572 env.repeatInvocation();
576 ClassInfo ci = env.getReferredClassInfo(objRef);
577 int nInstance = ci.getNumberOfDeclaredInstanceFields();
578 int nStatic = ci.getNumberOfStaticFields();
579 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", nInstance + nStatic);
582 for (i=0; i<nStatic; i++) {
583 FieldInfo fi = ci.getStaticField(i);
584 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
587 for (i=0; i<nInstance; i++) {
588 FieldInfo fi = ci.getDeclaredInstanceField(i);
589 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
596 public int getFields_____3Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef){
597 ClassInfo fci = getInitializedClassInfo(env, FIELD_CLASSNAME);
599 env.repeatInvocation();
603 ClassInfo ci = env.getReferredClassInfo(clsRef);
604 // interfaces might not be initialized yet, so we have to check first
605 Set<ClassInfo> ifcs = getInitializedInterfaces( env, ci);
607 env.repeatInvocation();
611 ArrayList<FieldInfo> fiList = new ArrayList<FieldInfo>();
612 for (; ci != null; ci = ci.getSuperClass()){
613 // the host VM returns them in order of declaration, but the spec says there is no guaranteed order so we keep it simple
614 for (FieldInfo fi : ci.getDeclaredInstanceFields()){
619 for (FieldInfo fi : ci.getDeclaredStaticFields()){
626 for (ClassInfo ciIfc : ifcs){
627 for (FieldInfo fi : ciIfc.getDeclaredStaticFields()){
628 fiList.add(fi); // there are no non-public fields in interfaces
632 int aref = env.newObjectArray("Ljava/lang/reflect/Field;", fiList.size());
634 for (FieldInfo fi : fiList){
635 env.setReferenceArrayElement(aref, j++, createFieldObject(env, fi, fci));
641 int getField (MJIEnv env, int clsRef, int nameRef, boolean isRecursiveLookup) {
642 ClassInfo ci = env.getReferredClassInfo( clsRef);
643 String fname = env.getStringObject(nameRef);
646 if (isRecursiveLookup) {
647 fi = ci.getInstanceField(fname);
649 fi = ci.getStaticField(fname);
652 fi = ci.getDeclaredInstanceField(fname);
654 fi = ci.getDeclaredStaticField(fname);
659 env.throwException("java.lang.NoSuchFieldException", fname);
663 // don't do a Field clinit before we know there is such a field
664 ClassInfo fci = getInitializedClassInfo( env, FIELD_CLASSNAME);
666 env.repeatInvocation();
670 return createFieldObject( env, fi, fci);
675 public int getDeclaredField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
676 return getField(env,clsRef,nameRef, false);
680 public int getField__Ljava_lang_String_2__Ljava_lang_reflect_Field_2 (MJIEnv env, int clsRef, int nameRef) {
681 return getField(env,clsRef,nameRef, true);
685 public int getModifiers____I (MJIEnv env, int clsRef){
686 ClassInfo ci = env.getReferredClassInfo(clsRef);
687 return ci.getModifiers();
691 public int getEnumConstants_____3Ljava_lang_Object_2 (MJIEnv env, int clsRef){
692 ClassInfo ci = env.getReferredClassInfo(clsRef);
694 if (env.requiresClinitExecution(ci)){
695 env.repeatInvocation();
699 if (ci.getSuperClass().getName().equals("java.lang.Enum")) {
700 ArrayList<FieldInfo> list = new ArrayList<FieldInfo>();
701 String cName = ci.getName();
703 for (FieldInfo fi : ci.getDeclaredStaticFields()) {
704 if (fi.isFinal() && cName.equals(fi.getType())){
709 int aRef = env.newObjectArray(cName, list.size());
710 StaticElementInfo sei = ci.getStaticElementInfo();
712 for (FieldInfo fi : list){
713 env.setReferenceArrayElement( aRef, i++, sei.getReferenceField(fi));
722 public int getInterfaces_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
723 ClassInfo ci = env.getReferredClassInfo(clsRef);
724 int aref = MJIEnv.NULL;
725 ThreadInfo ti = env.getThreadInfo();
727 // contrary to the API doc, this only returns the interfaces directly
728 // implemented by this class, not it's bases
729 // <2do> this is not exactly correct, since the interfaces should be ordered
730 Set<ClassInfo> interfaces = ci.getInterfaceClassInfos();
731 aref = env.newObjectArray("Ljava/lang/Class;", interfaces.size());
734 for (ClassInfo ifc: interfaces){
735 env.setReferenceArrayElement(aref, i++, ifc.getClassObjectRef());
743 * <2do> needs to load from the classfile location, NOT the MJIEnv (native) class
745 * @author Sebastian Gfeller (sebastian.gfeller@gmail.com)
746 * @author Tihomir Gvero (tihomir.gvero@gmail.com)
749 public int getByteArrayFromResourceStream__Ljava_lang_String_2___3B(MJIEnv env, int clsRef, int nameRef) {
750 String name = env.getStringObject(nameRef);
752 // <2do> this is not loading from the classfile location! fix it
753 InputStream is = env.getClass().getResourceAsStream(name);
757 // We assume that the entire input stream can be read at the moment,
758 // although this could break.
759 byte[] content = null;
761 content = new byte[is.available()];
763 } catch (IOException e) {
764 throw new RuntimeException(e);
766 // Now if everything worked, the content should be in the byte buffer.
767 // We put this buffer into the JPF VM.
768 return env.newByteArray(content);
772 public int getEnclosingClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef) {
773 ClassInfo ciEncl = env.getReferredClassInfo( clsRef).getEnclosingClassInfo();
779 if (ciEncl.initializeClass(env.getThreadInfo())) {
780 env.repeatInvocation();
784 return ciEncl.getClassObjectRef();
788 public int getDeclaredClasses_____3Ljava_lang_Class_2 (MJIEnv env, int clsRef){
789 ClassInfo ci = env.getReferredClassInfo(clsRef);
790 String[] innerClassNames = ci.getInnerClasses();
791 int aref = MJIEnv.NULL;
792 ThreadInfo ti = env.getThreadInfo();
794 MethodInfo mi = ti.getTopFrame().getPrevious().getMethodInfo();
795 // class of the method that includes the invocation of Class.getDeclaredClasses
796 ClassInfo cls = mi.getClassInfo();
798 // first resolve all the inner classes
799 int length = innerClassNames.length;
800 ClassInfo[] resolvedInnerClass = new ClassInfo[length];
801 for(int i=0; i<length; i++) {
803 resolvedInnerClass[i] = cls.resolveReferencedClass(innerClassNames[i]);
804 } catch(LoadOnJPFRequired lre) {
805 env.repeatInvocation();
810 aref = env.newObjectArray("Ljava/lang/Class;", innerClassNames.length);
811 for (int i=0; i<length; i++){
812 ClassInfo ici = resolvedInnerClass[i];
813 if (!ici.isRegistered()) {
814 ici.registerClass(ti);
816 env.setReferenceArrayElement(aref, i, ici.getClassObjectRef());
822 private String getCanonicalName (ClassInfo ci){
824 String canonicalName = getCanonicalName(ci.getComponentClassInfo());
825 if (canonicalName != null){
826 return canonicalName + "[]";
831 if (isLocalOrAnonymousClass(ci)) {
834 if (ci.getEnclosingClassInfo() == null){
837 String enclosingName = getCanonicalName(ci.getEnclosingClassInfo());
838 if (enclosingName == null){ return null; }
839 return enclosingName + "." + ci.getSimpleName();
844 public int getCanonicalName____Ljava_lang_String_2 (MJIEnv env, int clsRef){
845 ClassInfo ci = env.getReferredClassInfo(clsRef);
846 return env.newString(getCanonicalName(ci));
850 public boolean isAnnotation____Z (MJIEnv env, int clsObjRef){
851 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
852 return (ci.getModifiers() & 0x2000) != 0;
856 public boolean isAnnotationPresent__Ljava_lang_Class_2__Z (MJIEnv env, int clsObjRef, int annoClsObjRef){
857 ClassInfo ci = env.getReferredClassInfo(clsObjRef);
858 ClassInfo ciAnno = env.getReferredClassInfo(annoClsObjRef);
860 return ci.getAnnotation( ciAnno.getName()) != null;
864 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int robj){
865 ClassInfo ci = env.getReferredClassInfo(robj);
868 return env.newAnnotationProxies(ci.getDeclaredAnnotations());
869 } catch (ClinitRequired x){
870 env.handleClinitRequest(x.getRequiredClassInfo());
876 public int getEnclosingConstructor____Ljava_lang_reflect_Constructor_2 (MJIEnv env, int robj){
877 ClassInfo mci = getInitializedClassInfo(env, CONSTRUCTOR_CLASSNAME);
879 env.repeatInvocation();
882 ClassInfo ci = env.getReferredClassInfo(robj);
883 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
885 if ((enclosingMethod != null) && enclosingMethod.isCtor()){
886 return createMethodObject(env, mci, enclosingMethod);
892 public int getEnclosingMethod____Ljava_lang_reflect_Method_2 (MJIEnv env, int robj){
893 ClassInfo mci = getInitializedClassInfo(env, METHOD_CLASSNAME);
895 env.repeatInvocation();
898 ClassInfo ci = env.getReferredClassInfo(robj);
899 MethodInfo enclosingMethod = ci.getEnclosingMethodInfo();
901 if ((enclosingMethod != null) && !enclosingMethod.isCtor()){
902 return createMethodObject(env, mci, enclosingMethod);
908 public boolean isAnonymousClass____Z (MJIEnv env, int robj){
909 ClassInfo ci = env.getReferredClassInfo(robj);
911 if (ci.getName().contains("$")){
912 cname = ci.getName().substring(ci.getName().lastIndexOf('$') + 1);
914 return (cname == null) ? false : cname.matches("\\d+?");
918 public boolean isEnum____Z (MJIEnv env, int robj){
919 ClassInfo ci = env.getReferredClassInfo(robj);
923 // Similar to getEnclosingClass() except it returns null for the case of
926 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int clsRef){
927 ClassInfo ci = env.getReferredClassInfo(clsRef);
928 if (isLocalOrAnonymousClass(ci)){
931 return getEnclosingClass____Ljava_lang_Class_2(env, clsRef);
936 public boolean isLocalClass____Z (MJIEnv env, int robj){
937 ClassInfo ci = env.getReferredClassInfo(robj);
938 return isLocalOrAnonymousClass(ci) && !isAnonymousClass____Z(env, robj);
941 private boolean isLocalOrAnonymousClass (ClassInfo ci){
942 return (ci.getEnclosingMethodInfo() != null);
946 public boolean isMemberClass____Z (MJIEnv env, int robj){
947 ClassInfo ci = env.getReferredClassInfo(robj);
948 return (ci.getEnclosingClassInfo() != null) && !isLocalOrAnonymousClass(ci);
952 * Append the package name prefix of the class represented by robj, if the name is not
953 * absolute. OW, remove leading "/".
956 public int getResolvedName__Ljava_lang_String_2__Ljava_lang_String_2 (MJIEnv env, int robj, int resRef){
957 String rname = env.getStringObject(resRef);
958 ClassInfo ci = env.getReferredClassInfo(robj);
962 if (!rname.startsWith("/")) {
964 while (c.isArray()) {
965 c = c.getComponentClassInfo();
967 String baseName = c.getName();
968 int index = baseName.lastIndexOf('.');
970 rname = baseName.substring(0, index).replace('.', '/')
974 rname = rname.substring(1);
977 return env.newString(rname);