blob: 996d6a4f811f47b28a4fccc34bd4d7e5b82ae663 [file] [log] [blame]
Elliott Hughesd369bb72011-09-12 14:41:14 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni_internal.h"
18#include "class_linker.h"
Brian Carlstromf91c8c32011-09-21 17:30:34 -070019#include "class_loader.h"
Elliott Hughesd369bb72011-09-12 14:41:14 -070020#include "object.h"
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080021#include "object_utils.h"
Elliott Hughes80609252011-09-23 17:24:51 -070022#include "ScopedLocalRef.h"
Brian Carlstromf91c8c32011-09-21 17:30:34 -070023#include "ScopedUtfChars.h"
Elliott Hughesd369bb72011-09-12 14:41:14 -070024
25#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
26
27namespace art {
28
29namespace {
30
Brian Carlstromf91c8c32011-09-21 17:30:34 -070031// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
32jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
Brian Carlstromb82b6872011-10-26 17:18:07 -070033 ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Brian Carlstromf91c8c32011-09-21 17:30:34 -070034 ScopedUtfChars name(env, javaName);
35 if (name.c_str() == NULL) {
36 return NULL;
37 }
38
39 // We need to validate and convert the name (from x.y.z to x/y/z). This
40 // is especially handy for array types, since we want to avoid
41 // auto-generating bogus array classes.
Elliott Hughes906e6852011-10-28 14:52:10 -070042 if (!IsValidBinaryClassName(name.c_str())) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -070043 Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassNotFoundException;",
Brian Carlstromf91c8c32011-09-21 17:30:34 -070044 "Invalid name: %s", name.c_str());
45 return NULL;
46 }
47
48 std::string descriptor(DotToDescriptor(name.c_str()));
49 Object* loader = Decode<Object*>(env, javaLoader);
50 ClassLoader* class_loader = down_cast<ClassLoader*>(loader);
51 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
52 Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
Brian Carlstrom395520e2011-09-25 19:35:00 -070053 if (c == NULL) {
Elliott Hughesa7679b62012-01-24 17:15:23 -080054 // Convert NoClassDefFoundError to ClassNotFoundException.
Elliott Hughes844f9a02012-01-24 20:19:58 -080055 ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
Brian Carlstrom395520e2011-09-25 19:35:00 -070056 env->ExceptionClear();
Elliott Hughes844f9a02012-01-24 20:19:58 -080057 static jclass ClassNotFoundException_class = CacheClass(env, "java/lang/ClassNotFoundException");
58 static jmethodID ctor = env->GetMethodID(ClassNotFoundException_class, "<init>", "(Ljava/lang/String;Ljava/lang/Throwable;)V");
59 jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(ClassNotFoundException_class, ctor, javaName, cause.get()));
60 env->Throw(cnfe);
Brian Carlstrom395520e2011-09-25 19:35:00 -070061 return NULL;
62 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -070063 if (initialize) {
64 class_linker->EnsureInitialized(c, true);
65 }
66 return AddLocalReference<jclass>(env, c);
67}
68
Ian Rogers6d4d9fc2011-11-30 16:24:48 -080069jint Class_getAnnotationDirectoryOffset(JNIEnv* env, jclass javaClass) {
70 Class* c = Decode<Class*>(env, javaClass);
71 if (c->IsPrimitive() || c->IsArrayClass() || c->IsProxyClass()) {
72 return 0; // primitive, array and proxy classes don't have class definitions
73 }
74 const DexFile::ClassDef* class_def = ClassHelper(c).GetClassDef();
75 if (class_def == NULL) {
76 return 0; // not found
77 } else {
78 return class_def->annotations_off_;
79 }
80}
81
Elliott Hughes80609252011-09-23 17:24:51 -070082template<typename T>
83jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
84 jclass array_class = env->FindClass(array_class_name);
85 jobjectArray result = env->NewObjectArray(objects.size(), array_class, NULL);
86 for (size_t i = 0; i < objects.size(); ++i) {
87 ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
88 env->SetObjectArrayElement(result, i, object.get());
89 }
90 return result;
91}
92
93bool IsVisibleConstructor(Method* m, bool public_only) {
94 if (public_only && !m->IsPublic()) {
95 return false;
96 }
Ian Rogers9074b992011-10-26 17:41:55 -070097 if (m->IsStatic()) {
Elliott Hughes80609252011-09-23 17:24:51 -070098 return false;
99 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800100 return m->IsConstructor();
Elliott Hughes80609252011-09-23 17:24:51 -0700101}
102
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800103jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
Elliott Hughes80609252011-09-23 17:24:51 -0700104 Class* c = Decode<Class*>(env, javaClass);
105
106 std::vector<Method*> constructors;
107 for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
108 Method* m = c->GetDirectMethod(i);
109 if (IsVisibleConstructor(m, publicOnly)) {
110 constructors.push_back(m);
111 }
112 }
113
114 return ToArray(env, "java/lang/reflect/Constructor", constructors);
115}
116
117bool IsVisibleField(Field* f, bool public_only) {
Elliott Hughesc0dd3122011-09-26 10:15:43 -0700118 if (public_only && !f->IsPublic()) {
Elliott Hughes80609252011-09-23 17:24:51 -0700119 return false;
120 }
Elliott Hughes80609252011-09-23 17:24:51 -0700121 return true;
122}
123
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800124jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
Elliott Hughes80609252011-09-23 17:24:51 -0700125 Class* c = Decode<Class*>(env, javaClass);
126
127 std::vector<Field*> fields;
128 for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
129 Field* f = c->GetInstanceField(i);
130 if (IsVisibleField(f, publicOnly)) {
131 fields.push_back(f);
132 }
Jesse Wilson53494312011-11-29 16:43:09 -0500133 if (env->ExceptionOccurred()) {
134 return NULL;
135 }
Elliott Hughes80609252011-09-23 17:24:51 -0700136 }
137 for (size_t i = 0; i < c->NumStaticFields(); ++i) {
138 Field* f = c->GetStaticField(i);
139 if (IsVisibleField(f, publicOnly)) {
140 fields.push_back(f);
141 }
Jesse Wilson53494312011-11-29 16:43:09 -0500142 if (env->ExceptionOccurred()) {
143 return NULL;
144 }
Elliott Hughes80609252011-09-23 17:24:51 -0700145 }
146
147 return ToArray(env, "java/lang/reflect/Field", fields);
148}
149
150bool IsVisibleMethod(Method* m, bool public_only) {
151 if (public_only && !m->IsPublic()) {
152 return false;
153 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800154 if (m->IsConstructor()) {
Elliott Hughes80609252011-09-23 17:24:51 -0700155 return false;
156 }
Elliott Hughes80609252011-09-23 17:24:51 -0700157 return true;
158}
159
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800160jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboolean publicOnly) {
Elliott Hughes80609252011-09-23 17:24:51 -0700161 Class* c = Decode<Class*>(env, javaClass);
Elliott Hughes80609252011-09-23 17:24:51 -0700162 std::vector<Method*> methods;
163 for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
164 Method* m = c->GetVirtualMethod(i);
165 if (IsVisibleMethod(m, publicOnly)) {
166 methods.push_back(m);
167 }
Jesse Wilson53494312011-11-29 16:43:09 -0500168 if (env->ExceptionOccurred()) {
169 return NULL;
170 }
Elliott Hughes80609252011-09-23 17:24:51 -0700171 }
172 for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
173 Method* m = c->GetDirectMethod(i);
174 if (IsVisibleMethod(m, publicOnly)) {
175 methods.push_back(m);
176 }
Jesse Wilson53494312011-11-29 16:43:09 -0500177 if (env->ExceptionOccurred()) {
178 return NULL;
179 }
Elliott Hughes80609252011-09-23 17:24:51 -0700180 }
181
182 return ToArray(env, "java/lang/reflect/Method", methods);
183}
184
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700185jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
186 return JNI_FALSE;
187}
188
Jesse Wilson6bf19152011-09-29 13:12:33 -0400189jobject Class_getDex(JNIEnv* env, jobject javaClass) {
190 Class* c = Decode<Class*>(env, javaClass);
191
192 DexCache* dex_cache = c->GetDexCache();
193 if (dex_cache == NULL) {
194 return NULL;
195 }
196
197 return Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache).GetDexObject(env);
198}
199
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800200jint Class_getNonInnerClassModifiers(JNIEnv* env, jclass javaClass) {
Elliott Hughes9dcc79d2011-10-02 16:31:10 -0700201 Class* c = Decode<Class*>(env, javaClass);
Jesse Wilson163c4642011-10-12 10:42:15 -0400202 return c->GetAccessFlags() & kAccJavaFlagsMask;
Elliott Hughes9dcc79d2011-10-02 16:31:10 -0700203}
204
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800205jobject Class_getClassLoaderNative(JNIEnv* env, jclass javaClass) {
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700206 Class* c = Decode<Class*>(env, javaClass);
Elliott Hughes1bba14f2011-12-01 18:00:36 -0800207 Object* result = c->GetClassLoader();
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700208 return AddLocalReference<jobject>(env, result);
209}
210
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800211jclass Class_getComponentType(JNIEnv* env, jclass javaClass) {
212 return AddLocalReference<jclass>(env, Decode<Class*>(env, javaClass)->GetComponentType());
Elliott Hughesd369bb72011-09-12 14:41:14 -0700213}
214
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800215bool MethodMatches(MethodHelper* mh, const std::string& name, ObjectArray<Class>* arg_array) {
216 if (name != mh->GetName()) {
Elliott Hughes418d20f2011-09-22 14:00:39 -0700217 return false;
218 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800219 const DexFile::TypeList* m_type_list = mh->GetParameterTypeList();
220 uint32_t m_type_list_size = m_type_list == NULL ? 0 : m_type_list->Size();
221 uint32_t sig_length = arg_array->GetLength();
222
223 if (m_type_list_size != sig_length) {
Elliott Hughes418d20f2011-09-22 14:00:39 -0700224 return false;
225 }
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800226
227 for (uint32_t i = 0; i < sig_length; i++) {
228 if (mh->GetClassFromTypeIdx(m_type_list->GetTypeItem(i).type_idx_) != arg_array->Get(i)) {
229 return false;
230 }
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500231 }
Elliott Hughes418d20f2011-09-22 14:00:39 -0700232 return true;
233}
234
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800235Method* FindConstructorOrMethodInArray(ObjectArray<Method>* methods, const std::string& name,
236 ObjectArray<Class>* arg_array) {
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500237 if (methods == NULL) {
238 return NULL;
239 }
240 Method* result = NULL;
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800241 MethodHelper mh;
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500242 for (int32_t i = 0; i < methods->GetLength(); ++i) {
243 Method* method = methods->Get(i);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800244 mh.ChangeMethod(method);
245 if (method->IsMiranda() || !MethodMatches(&mh, name, arg_array)) {
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500246 continue;
247 }
248
249 result = method;
250
251 // Covariant return types permit the class to define multiple
252 // methods with the same name and parameter types. Prefer to return
253 // a non-synthetic method in such situations. We may still return
254 // a synthetic method to handle situations like escalated visibility.
255 if (!method->IsSynthetic()) {
256 break;
257 }
258 }
259 return result;
260}
261
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800262jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass javaClass, jstring javaName,
263 jobjectArray javaArgs) {
Elliott Hughes418d20f2011-09-22 14:00:39 -0700264 Class* c = Decode<Class*>(env, javaClass);
Elliott Hughes95572412011-12-13 18:14:20 -0800265 std::string name(Decode<String*>(env, javaName)->ToModifiedUtf8());
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800266 ObjectArray<Class>* arg_array = Decode<ObjectArray<Class>*>(env, javaArgs);
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700267
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800268 Method* m = FindConstructorOrMethodInArray(c->GetDirectMethods(), name, arg_array);
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500269 if (m == NULL) {
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800270 m = FindConstructorOrMethodInArray(c->GetVirtualMethods(), name, arg_array);
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700271 }
272
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500273 if (m != NULL) {
Jesse Wilson8ea36f82011-11-21 10:35:06 -0500274 return AddLocalReference<jobject>(env, m);
275 } else {
276 return NULL;
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700277 }
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700278}
279
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800280jobject Class_getDeclaredFieldNative(JNIEnv* env, jclass jklass, jobject jname) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700281 Class* klass = Decode<Class*>(env, jklass);
282 DCHECK(klass->IsClass());
283 String* name = Decode<String*>(env, jname);
Elliott Hughesdbb40792011-11-18 17:05:22 -0800284 DCHECK(name->GetClass()->IsStringClass());
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700285
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800286 FieldHelper fh;
Elliott Hughes80609252011-09-23 17:24:51 -0700287 for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700288 Field* f = klass->GetInstanceField(i);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800289 fh.ChangeField(f);
290 if (name->Equals(fh.GetName())) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700291 return AddLocalReference<jclass>(env, f);
292 }
293 }
294 for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
295 Field* f = klass->GetStaticField(i);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800296 fh.ChangeField(f);
297 if (name->Equals(fh.GetName())) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700298 return AddLocalReference<jclass>(env, f);
299 }
300 }
301 return NULL;
302}
303
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700304/*
305 * private native String getNameNative()
306 *
307 * Return the class' name. The exact format is bizarre, but it's the specified
308 * behavior: keywords for primitive types, regular "[I" form for primitive
309 * arrays (so "int" but "[I"), and arrays of reference types written
310 * between "L" and ";" but with dots rather than slashes (so "java.lang.String"
311 * but "[Ljava.lang.String;"). Madness.
312 */
313jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
314 Class* c = Decode<Class*>(env, javaThis);
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800315 std::string descriptor(ClassHelper(c).GetDescriptor());
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700316 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
317 // The descriptor indicates that this is the class for
318 // a primitive type; special-case the return value.
319 const char* name = NULL;
320 switch (descriptor[0]) {
321 case 'Z': name = "boolean"; break;
322 case 'B': name = "byte"; break;
323 case 'C': name = "char"; break;
324 case 'S': name = "short"; break;
325 case 'I': name = "int"; break;
326 case 'J': name = "long"; break;
327 case 'F': name = "float"; break;
328 case 'D': name = "double"; break;
329 case 'V': name = "void"; break;
330 default:
331 LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]);
332 }
333 return env->NewStringUTF(name);
334 }
335
336 // Convert the UTF-8 name to a java.lang.String. The
337 // name must use '.' to separate package components.
338 if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') {
339 descriptor.erase(0, 1);
340 descriptor.erase(descriptor.size() - 1);
341 }
342 std::replace(descriptor.begin(), descriptor.end(), '/', '.');
343 return env->NewStringUTF(descriptor.c_str());
344}
345
346jclass Class_getSuperclass(JNIEnv* env, jobject javaThis) {
347 Class* c = Decode<Class*>(env, javaThis);
348 Class* result = c->GetSuperClass();
349 return AddLocalReference<jclass>(env, result);
350}
351
Elliott Hughesdd8df692011-09-23 14:42:41 -0700352jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) {
Brian Carlstromb82b6872011-10-26 17:18:07 -0700353 ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Elliott Hughesdd8df692011-09-23 14:42:41 -0700354 Class* lhs = Decode<Class*>(env, javaLhs);
355 Class* rhs = Decode<Class*>(env, javaRhs);
356 if (rhs == NULL) {
357 Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "class == null");
358 return JNI_FALSE;
359 }
360 return lhs->IsAssignableFrom(rhs) ? JNI_TRUE : JNI_FALSE;
361}
362
363jboolean Class_isInstance(JNIEnv* env, jobject javaClass, jobject javaObject) {
364 Class* c = Decode<Class*>(env, javaClass);
365 Object* o = Decode<Object*>(env, javaObject);
366 if (o == NULL) {
367 return JNI_FALSE;
368 }
Brian Carlstrom5d40f182011-09-26 22:29:18 -0700369 return o->InstanceOf(c) ? JNI_TRUE : JNI_FALSE;
Elliott Hughesdd8df692011-09-23 14:42:41 -0700370}
371
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700372jboolean Class_isInterface(JNIEnv* env, jobject javaThis) {
373 Class* c = Decode<Class*>(env, javaThis);
374 return c->IsInterface();
375}
376
377jboolean Class_isPrimitive(JNIEnv* env, jobject javaThis) {
378 Class* c = Decode<Class*>(env, javaThis);
379 return c->IsPrimitive();
380}
381
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700382// Validate method/field access.
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800383bool CheckMemberAccess(const Class* access_from, Class* access_to, uint32_t member_flags) {
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700384 // quick accept for public access */
385 if (member_flags & kAccPublic) {
386 return true;
387 }
388
389 // quick accept for access from same class
390 if (access_from == access_to) {
391 return true;
392 }
393
394 // quick reject for private access from another class
395 if (member_flags & kAccPrivate) {
396 return false;
397 }
398
399 // Semi-quick test for protected access from a sub-class, which may or
400 // may not be in the same package.
401 if (member_flags & kAccProtected) {
402 if (access_from->IsSubClass(access_to)) {
403 return true;
404 }
405 }
406
407 // Allow protected and private access from other classes in the same
408 return access_from->IsInSamePackage(access_to);
409}
410
411jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) {
Brian Carlstromb82b6872011-10-26 17:18:07 -0700412 ScopedThreadStateChange tsc(Thread::Current(), Thread::kRunnable);
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700413 Class* c = Decode<Class*>(env, javaThis);
414 if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700415 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800416 "Class %s can not be instantiated", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700417 return NULL;
418 }
419
Elliott Hughes2a20cfd2011-09-23 19:30:41 -0700420 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
421 return NULL;
422 }
423
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700424 Method* init = c->FindDirectMethod("<init>", "()V");
425 if (init == NULL) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700426 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800427 "Class %s has no default <init>()V constructor", PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700428 return NULL;
429 }
430
431 // Verify access from the call site.
432 //
433 // First, make sure the method invoking Class.newInstance() has permission
434 // to access the class.
435 //
436 // Second, make sure it has permission to invoke the constructor. The
437 // constructor must be public or, if the caller is in the same package,
438 // have package scope.
439 // TODO: need SmartFrame (Thread::WalkStack-like iterator).
440 Frame frame = Thread::Current()->GetTopOfStack();
441 frame.Next();
442 frame.Next();
443 Method* caller_caller = frame.GetMethod();
444 Class* caller_class = caller_caller->GetDeclaringClass();
445
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800446 ClassHelper caller_ch(caller_class);
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700447 if (!caller_class->CanAccess(c)) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700448 Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
449 "Class %s is not accessible from class %s",
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800450 PrettyDescriptor(ClassHelper(c).GetDescriptor()).c_str(),
451 PrettyDescriptor(caller_ch.GetDescriptor()).c_str());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700452 return NULL;
453 }
454 if (!CheckMemberAccess(caller_class, init->GetDeclaringClass(), init->GetAccessFlags())) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700455 Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
456 "%s is not accessible from class %s",
457 PrettyMethod(init).c_str(),
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800458 PrettyDescriptor(caller_ch.GetDescriptor()).c_str());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700459 return NULL;
460 }
461
462 Object* new_obj = c->AllocObject();
463 if (new_obj == NULL) {
464 DCHECK(Thread::Current()->IsExceptionPending());
465 return NULL;
466 }
467
468 // invoke constructor; unlike reflection calls, we don't wrap exceptions
469 jclass jklass = AddLocalReference<jclass>(env, c);
470 jmethodID mid = EncodeMethod(init);
471 return env->NewObject(jklass, mid);
472}
473
Elliott Hughesd369bb72011-09-12 14:41:14 -0700474static JNINativeMethod gMethods[] = {
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700475 NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700476 NATIVE_METHOD(Class, desiredAssertionStatus, "()Z"),
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800477 NATIVE_METHOD(Class, getAnnotationDirectoryOffset, "()I"),
478 NATIVE_METHOD(Class, getClassLoaderNative, "()Ljava/lang/ClassLoader;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700479 NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800480 NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
481 NATIVE_METHOD(Class, getDeclaredConstructors, "(Z)[Ljava/lang/reflect/Constructor;"),
482 NATIVE_METHOD(Class, getDeclaredFieldNative, "(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
483 NATIVE_METHOD(Class, getDeclaredFields, "(Z)[Ljava/lang/reflect/Field;"),
484 NATIVE_METHOD(Class, getDeclaredMethods, "(Z)[Ljava/lang/reflect/Method;"),
Jesse Wilson6bf19152011-09-29 13:12:33 -0400485 NATIVE_METHOD(Class, getDex, "()Lcom/android/dex/Dex;"),
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800486 NATIVE_METHOD(Class, getNonInnerClassModifiers, "()I"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700487 NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700488 NATIVE_METHOD(Class, getSuperclass, "()Ljava/lang/Class;"),
Elliott Hughesdd8df692011-09-23 14:42:41 -0700489 NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"),
490 NATIVE_METHOD(Class, isInstance, "(Ljava/lang/Object;)Z"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700491 NATIVE_METHOD(Class, isInterface, "()Z"),
492 NATIVE_METHOD(Class, isPrimitive, "()Z"),
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700493 NATIVE_METHOD(Class, newInstanceImpl, "()Ljava/lang/Object;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700494};
495
496} // namespace
497
498void register_java_lang_Class(JNIEnv* env) {
499 jniRegisterNativeMethods(env, "java/lang/Class", gMethods, NELEM(gMethods));
500}
501
502} // namespace art