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.lang.reflect.Modifier;
22 import gov.nasa.jpf.Config;
23 import gov.nasa.jpf.annotation.MJI;
24 import gov.nasa.jpf.util.MethodInfoRegistry;
25 import gov.nasa.jpf.util.RunListener;
26 import gov.nasa.jpf.util.RunRegistry;
29 * native peer for rudimentary constructor reflection.
31 * Unfortunately, this is quite redundant to the Method peer, but Constructor
32 * is not a Method subclass, and hence we can't rely on it's initialization
34 public class JPF_java_lang_reflect_Constructor extends NativePeer {
36 static MethodInfoRegistry registry;
38 public static boolean init (Config conf) {
39 // this is an example of how to handle cross-initialization between
40 // native peers - this might also get explicitly called by the java.lang.Class
41 // peer, since it creates Constructor objects. Here we have to make sure
42 // we only reset between JPF runs
44 if (registry == null){
45 registry = new MethodInfoRegistry();
47 RunRegistry.getDefaultRegistry().addListener( new RunListener() {
49 public void reset (RunRegistry reg){
57 static int createConstructorObject (MJIEnv env, ClassInfo ciCtor, MethodInfo mi){
58 // note - it is the callers responsibility to ensure Constructor is properly initialized
60 int regIdx = registry.registerMethodInfo(mi);
61 int eidx = env.newObject(ciCtor);
62 ElementInfo ei = env.getModifiableElementInfo(eidx);
64 ei.setIntField("regIdx", regIdx);
68 static MethodInfo getMethodInfo (MJIEnv env, int objRef){
69 return registry.getMethodInfo(env,objRef, "regIdx");
73 public int getName____Ljava_lang_String_2 (MJIEnv env, int objRef) {
74 MethodInfo mi = getMethodInfo(env, objRef);
76 int nameRef = env.getReferenceField( objRef, "name");
77 if (nameRef == MJIEnv.NULL) {
78 nameRef = env.newString(mi.getName());
79 env.setReferenceField(objRef, "name", nameRef);
85 // <2do> .. and some more delegations to JPF_java_lang_Method
88 public int newInstance___3Ljava_lang_Object_2__Ljava_lang_Object_2 (MJIEnv env, int mthRef, int argsRef) {
89 ThreadInfo ti = env.getThreadInfo();
90 DirectCallStackFrame frame = ti.getReturnedDirectCall();
91 MethodInfo miCallee = getMethodInfo(env,mthRef);
93 if (frame == null) { // first time
94 ClassInfo ci = miCallee.getClassInfo();
97 env.throwException("java.lang.InstantiationException");
101 int objRef = env.newObjectOfUncheckedClass( ci);
102 frame = miCallee.createDirectCallStackFrame( ti, 1);
103 frame.setReflection();
105 frame.setLocalReferenceVariable(0, objRef); // (1) store the objRef for retrieval during re-exec
107 int argOffset = frame.setReferenceArgument(0, objRef, null);
108 if (!JPF_java_lang_reflect_Method.pushUnboxedArguments( env, miCallee, frame, argOffset, argsRef)) {
109 // we've got a IllegalArgumentException
114 ci.initializeClass(ti);
116 env.repeatInvocation();
119 } else { // reflection call returned
120 int objRef = frame.getLocalVariable(0); // that's the object ref we stored in (1)
126 public int getParameterTypes_____3Ljava_lang_Class_2 (MJIEnv env, int objRef){
127 // kind of dangerous, but we don't refer to any fields and the underlying JPF construct
128 // (MethodInfo) is the same, so we just delegate to avoid copying non-trivial code
129 return JPF_java_lang_reflect_Method.getParameterTypes (env, getMethodInfo(env,objRef));
133 public int getAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef){
134 // <2do> check if ctor annotations are inherited, which is a bit off
135 return JPF_java_lang_reflect_Method.getAnnotations( env, getMethodInfo(env,objRef));
139 public int getDeclaredAnnotations_____3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef){
140 return JPF_java_lang_reflect_Method.getDeclaredAnnotations( env, getMethodInfo(env,objRef));
144 public int getAnnotation__Ljava_lang_Class_2__Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef, int annotationClsRef) {
145 return JPF_java_lang_reflect_Method.getAnnotation( env, getMethodInfo(env,objRef), annotationClsRef);
149 public int getParameterAnnotations_____3_3Ljava_lang_annotation_Annotation_2 (MJIEnv env, int objRef){
150 return JPF_java_lang_reflect_Method.getParameterAnnotations( env, getMethodInfo(env,objRef));
154 public int getModifiers____I (MJIEnv env, int objRef){
155 MethodInfo mi = getMethodInfo(env, objRef);
156 return mi.getModifiers();
160 public int getDeclaringClass____Ljava_lang_Class_2 (MJIEnv env, int objRef){
161 MethodInfo mi = getMethodInfo(env, objRef);
162 ClassInfo ci = mi.getClassInfo();
163 // can't get a Constructor object w/o having initialized it's declaring class first
164 return ci.getClassObjectRef();
168 public int toString____Ljava_lang_String_2 (MJIEnv env, int objRef){
169 StringBuilder sb = new StringBuilder();
171 MethodInfo mi = getMethodInfo(env, objRef);
173 sb.append(Modifier.toString(mi.getModifiers()));
176 sb.append(mi.getClassInfo().getName());
179 String[] at = mi.getArgumentTypeNames();
180 for (int i=0; i<at.length; i++){
181 if (i>0) sb.append(',');
187 int sref = env.newString(sb.toString());
192 public boolean equals__Ljava_lang_Object_2__Z (MJIEnv env, int objRef, int mthRef){
193 ElementInfo ei = env.getElementInfo(mthRef);
194 ClassInfo ci = ClassLoaderInfo.getSystemResolvedClassInfo(JPF_java_lang_Class.CONSTRUCTOR_CLASSNAME);
196 if (ei.getClassInfo() == ci){
197 MethodInfo mi1 = getMethodInfo(env, objRef);
198 MethodInfo mi2 = getMethodInfo(env, mthRef);
199 if (mi1.getClassInfo() == mi2.getClassInfo()){
200 if (mi1.getName().equals(mi2.getName())){
201 if (mi1.getReturnType().equals(mi2.getReturnType())){
202 byte[] params1 = mi1.getArgumentTypes();
203 byte[] params2 = mi2.getArgumentTypes();
204 if (params1.length == params2.length){
205 for (int i = 0; i < params1.length; i++){
206 if (params1[i] != params2[i])
219 public int hashCode____I (MJIEnv env, int objRef){
220 MethodInfo ctor = getMethodInfo(env, objRef);
221 return ctor.getClassName().hashCode();