blob: d2dd2eaf100676136c0738b638f611e0bdc8406c [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"
Elliott Hughes80609252011-09-23 17:24:51 -070021#include "ScopedLocalRef.h"
Brian Carlstromf91c8c32011-09-21 17:30:34 -070022#include "ScopedUtfChars.h"
Elliott Hughesd369bb72011-09-12 14:41:14 -070023
24#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
25
26namespace art {
27
28namespace {
29
Brian Carlstromf91c8c32011-09-21 17:30:34 -070030// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
31jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
32 ScopedUtfChars name(env, javaName);
33 if (name.c_str() == NULL) {
34 return NULL;
35 }
36
37 // We need to validate and convert the name (from x.y.z to x/y/z). This
38 // is especially handy for array types, since we want to avoid
39 // auto-generating bogus array classes.
40 if (!IsValidClassName(name.c_str(), true, true)) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -070041 Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassNotFoundException;",
Brian Carlstromf91c8c32011-09-21 17:30:34 -070042 "Invalid name: %s", name.c_str());
43 return NULL;
44 }
45
46 std::string descriptor(DotToDescriptor(name.c_str()));
47 Object* loader = Decode<Object*>(env, javaLoader);
48 ClassLoader* class_loader = down_cast<ClassLoader*>(loader);
49 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
50 Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
Brian Carlstrom395520e2011-09-25 19:35:00 -070051 if (c == NULL) {
52 // Convert NoClassDefFoundError to ClassNotFoundException
53 // TODO: chain exceptions?
54 DCHECK(env->ExceptionCheck());
55 env->ExceptionClear();
Elliott Hughes5cb5ad22011-10-02 12:13:39 -070056 Thread::Current()->ThrowNewException("Ljava/lang/ClassNotFoundException;", name.c_str());
Brian Carlstrom395520e2011-09-25 19:35:00 -070057 return NULL;
58 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -070059 if (initialize) {
60 class_linker->EnsureInitialized(c, true);
61 }
62 return AddLocalReference<jclass>(env, c);
63}
64
Elliott Hughes80609252011-09-23 17:24:51 -070065template<typename T>
66jobjectArray ToArray(JNIEnv* env, const char* array_class_name, const std::vector<T*>& objects) {
67 jclass array_class = env->FindClass(array_class_name);
68 jobjectArray result = env->NewObjectArray(objects.size(), array_class, NULL);
69 for (size_t i = 0; i < objects.size(); ++i) {
70 ScopedLocalRef<jobject> object(env, AddLocalReference<jobject>(env, objects[i]));
71 env->SetObjectArrayElement(result, i, object.get());
72 }
73 return result;
74}
75
76bool IsVisibleConstructor(Method* m, bool public_only) {
77 if (public_only && !m->IsPublic()) {
78 return false;
79 }
80 if (m->IsMiranda() || m->IsStatic()) {
81 return false;
82 }
83 if (m->GetName()->CharAt(0) != '<') {
84 return false;
85 }
86 m->InitJavaFields();
87 return true;
88}
89
90jobjectArray Class_getDeclaredConstructors(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
91 Class* c = Decode<Class*>(env, javaClass);
92
93 std::vector<Method*> constructors;
94 for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
95 Method* m = c->GetDirectMethod(i);
96 if (IsVisibleConstructor(m, publicOnly)) {
97 constructors.push_back(m);
98 }
99 }
100
101 return ToArray(env, "java/lang/reflect/Constructor", constructors);
102}
103
104bool IsVisibleField(Field* f, bool public_only) {
Elliott Hughesc0dd3122011-09-26 10:15:43 -0700105 if (public_only && !f->IsPublic()) {
Elliott Hughes80609252011-09-23 17:24:51 -0700106 return false;
107 }
108 f->InitJavaFields();
109 return true;
110}
111
112jobjectArray Class_getDeclaredFields(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
113 Class* c = Decode<Class*>(env, javaClass);
114
115 std::vector<Field*> fields;
116 for (size_t i = 0; i < c->NumInstanceFields(); ++i) {
117 Field* f = c->GetInstanceField(i);
118 if (IsVisibleField(f, publicOnly)) {
119 fields.push_back(f);
120 }
121 }
122 for (size_t i = 0; i < c->NumStaticFields(); ++i) {
123 Field* f = c->GetStaticField(i);
124 if (IsVisibleField(f, publicOnly)) {
125 fields.push_back(f);
126 }
127 }
128
129 return ToArray(env, "java/lang/reflect/Field", fields);
130}
131
132bool IsVisibleMethod(Method* m, bool public_only) {
133 if (public_only && !m->IsPublic()) {
134 return false;
135 }
136 if (m->IsMiranda()) {
137 return false;
138 }
139 if (m->GetName()->CharAt(0) == '<') {
140 return false;
141 }
142 m->InitJavaFields();
143 return true;
144}
145
146jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass, jclass javaClass, jboolean publicOnly) {
147 Class* c = Decode<Class*>(env, javaClass);
148
149 std::vector<Method*> methods;
150 for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
151 Method* m = c->GetVirtualMethod(i);
152 if (IsVisibleMethod(m, publicOnly)) {
153 methods.push_back(m);
154 }
155 }
156 for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
157 Method* m = c->GetDirectMethod(i);
158 if (IsVisibleMethod(m, publicOnly)) {
159 methods.push_back(m);
160 }
161 }
162
163 return ToArray(env, "java/lang/reflect/Method", methods);
164}
165
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700166jboolean Class_desiredAssertionStatus(JNIEnv* env, jobject javaThis) {
167 return JNI_FALSE;
168}
169
Jesse Wilson6bf19152011-09-29 13:12:33 -0400170jobject Class_getDex(JNIEnv* env, jobject javaClass) {
171 Class* c = Decode<Class*>(env, javaClass);
172
173 DexCache* dex_cache = c->GetDexCache();
174 if (dex_cache == NULL) {
175 return NULL;
176 }
177
178 return Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache).GetDexObject(env);
179}
180
Elliott Hughes9dcc79d2011-10-02 16:31:10 -0700181jint Class_getModifiers(JNIEnv* env, jclass, jclass javaClass, jboolean ignoreInner) {
182 Class* c = Decode<Class*>(env, javaClass);
183 jint flags = c->GetAccessFlags() & kAccJavaFlagsMask;
184 if (!ignoreInner) {
185 UNIMPLEMENTED(WARNING) << "inner class modifiers";
186 }
187 return flags;
188}
189
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700190jobject Class_getClassLoader(JNIEnv* env, jclass, jobject javaClass) {
191 Class* c = Decode<Class*>(env, javaClass);
192 Object* result = reinterpret_cast<Object*>(const_cast<ClassLoader*>(c->GetClassLoader()));
193 return AddLocalReference<jobject>(env, result);
194}
195
Elliott Hughesd369bb72011-09-12 14:41:14 -0700196jclass Class_getComponentType(JNIEnv* env, jobject javaThis) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -0700197 return AddLocalReference<jclass>(env, Decode<Class*>(env, javaThis)->GetComponentType());
Elliott Hughesd369bb72011-09-12 14:41:14 -0700198}
199
Elliott Hughes418d20f2011-09-22 14:00:39 -0700200bool MethodMatches(Method* m, String* name, const std::string& signature) {
201 if (!m->GetName()->Equals(name)) {
202 return false;
203 }
204 std::string method_signature = m->GetSignature()->ToModifiedUtf8();
205 if (!StringPiece(method_signature).starts_with(signature)) {
206 return false;
207 }
208 m->InitJavaFields();
209 return true;
210}
211
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700212jobject Class_getDeclaredConstructorOrMethod(JNIEnv* env, jclass,
Elliott Hughes418d20f2011-09-22 14:00:39 -0700213 jclass javaClass, jstring javaName, jobjectArray javaSignature) {
214 Class* c = Decode<Class*>(env, javaClass);
215 String* name = Decode<String*>(env, javaName);
216 ObjectArray<Class>* signature_array = Decode<ObjectArray<Class>*>(env, javaSignature);
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700217
Elliott Hughes418d20f2011-09-22 14:00:39 -0700218 std::string signature;
219 signature += "(";
220 for (int i = 0; i < signature_array->GetLength(); i++) {
221 signature += signature_array->Get(i)->GetDescriptor()->ToModifiedUtf8();
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700222 }
Elliott Hughes418d20f2011-09-22 14:00:39 -0700223 signature += ")";
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700224
Elliott Hughes418d20f2011-09-22 14:00:39 -0700225 for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
226 Method* m = c->GetVirtualMethod(i);
227 if (MethodMatches(m, name, signature)) {
228 return AddLocalReference<jobject>(env, m);
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700229 }
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700230 }
231
Elliott Hughes418d20f2011-09-22 14:00:39 -0700232 for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
233 Method* m = c->GetDirectMethod(i);
234 if (MethodMatches(m, name, signature)) {
235 return AddLocalReference<jobject>(env, m);
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700236 }
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700237 }
238
239 return NULL;
240}
241
242jobject Class_getDeclaredField(JNIEnv* env, jclass, jclass jklass, jobject jname) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700243 Class* klass = Decode<Class*>(env, jklass);
244 DCHECK(klass->IsClass());
245 String* name = Decode<String*>(env, jname);
246 DCHECK(name->IsString());
247
Elliott Hughes80609252011-09-23 17:24:51 -0700248 for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700249 Field* f = klass->GetInstanceField(i);
250 if (f->GetName()->Equals(name)) {
Elliott Hughes80609252011-09-23 17:24:51 -0700251 f->InitJavaFields();
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700252 return AddLocalReference<jclass>(env, f);
253 }
254 }
255 for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
256 Field* f = klass->GetStaticField(i);
257 if (f->GetName()->Equals(name)) {
Elliott Hughes80609252011-09-23 17:24:51 -0700258 f->InitJavaFields();
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700259 return AddLocalReference<jclass>(env, f);
260 }
261 }
262 return NULL;
263}
264
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700265jclass Class_getDeclaringClass(JNIEnv* env, jobject javaThis) {
266 UNIMPLEMENTED(WARNING) << "needs annotations";
267 return NULL;
268}
269
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700270/*
271 * private native String getNameNative()
272 *
273 * Return the class' name. The exact format is bizarre, but it's the specified
274 * behavior: keywords for primitive types, regular "[I" form for primitive
275 * arrays (so "int" but "[I"), and arrays of reference types written
276 * between "L" and ";" but with dots rather than slashes (so "java.lang.String"
277 * but "[Ljava.lang.String;"). Madness.
278 */
279jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
280 Class* c = Decode<Class*>(env, javaThis);
281 std::string descriptor(c->GetDescriptor()->ToModifiedUtf8());
282 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
283 // The descriptor indicates that this is the class for
284 // a primitive type; special-case the return value.
285 const char* name = NULL;
286 switch (descriptor[0]) {
287 case 'Z': name = "boolean"; break;
288 case 'B': name = "byte"; break;
289 case 'C': name = "char"; break;
290 case 'S': name = "short"; break;
291 case 'I': name = "int"; break;
292 case 'J': name = "long"; break;
293 case 'F': name = "float"; break;
294 case 'D': name = "double"; break;
295 case 'V': name = "void"; break;
296 default:
297 LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]);
298 }
299 return env->NewStringUTF(name);
300 }
301
302 // Convert the UTF-8 name to a java.lang.String. The
303 // name must use '.' to separate package components.
304 if (descriptor.size() > 2 && descriptor[0] == 'L' && descriptor[descriptor.size() - 1] == ';') {
305 descriptor.erase(0, 1);
306 descriptor.erase(descriptor.size() - 1);
307 }
308 std::replace(descriptor.begin(), descriptor.end(), '/', '.');
309 return env->NewStringUTF(descriptor.c_str());
310}
311
312jclass Class_getSuperclass(JNIEnv* env, jobject javaThis) {
313 Class* c = Decode<Class*>(env, javaThis);
314 Class* result = c->GetSuperClass();
315 return AddLocalReference<jclass>(env, result);
316}
317
318jboolean Class_isAnonymousClass(JNIEnv* env, jobject javaThis) {
319 UNIMPLEMENTED(WARNING) << "needs annotations";
320 return JNI_FALSE;
321}
322
Elliott Hughesdd8df692011-09-23 14:42:41 -0700323jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) {
324 Class* lhs = Decode<Class*>(env, javaLhs);
325 Class* rhs = Decode<Class*>(env, javaRhs);
326 if (rhs == NULL) {
327 Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "class == null");
328 return JNI_FALSE;
329 }
330 return lhs->IsAssignableFrom(rhs) ? JNI_TRUE : JNI_FALSE;
331}
332
333jboolean Class_isInstance(JNIEnv* env, jobject javaClass, jobject javaObject) {
334 Class* c = Decode<Class*>(env, javaClass);
335 Object* o = Decode<Object*>(env, javaObject);
336 if (o == NULL) {
337 return JNI_FALSE;
338 }
Brian Carlstrom5d40f182011-09-26 22:29:18 -0700339 return o->InstanceOf(c) ? JNI_TRUE : JNI_FALSE;
Elliott Hughesdd8df692011-09-23 14:42:41 -0700340}
341
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700342jboolean Class_isInterface(JNIEnv* env, jobject javaThis) {
343 Class* c = Decode<Class*>(env, javaThis);
344 return c->IsInterface();
345}
346
347jboolean Class_isPrimitive(JNIEnv* env, jobject javaThis) {
348 Class* c = Decode<Class*>(env, javaThis);
349 return c->IsPrimitive();
350}
351
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700352// Validate method/field access.
353bool CheckMemberAccess(const Class* access_from, const Class* access_to, uint32_t member_flags) {
354 // quick accept for public access */
355 if (member_flags & kAccPublic) {
356 return true;
357 }
358
359 // quick accept for access from same class
360 if (access_from == access_to) {
361 return true;
362 }
363
364 // quick reject for private access from another class
365 if (member_flags & kAccPrivate) {
366 return false;
367 }
368
369 // Semi-quick test for protected access from a sub-class, which may or
370 // may not be in the same package.
371 if (member_flags & kAccProtected) {
372 if (access_from->IsSubClass(access_to)) {
373 return true;
374 }
375 }
376
377 // Allow protected and private access from other classes in the same
378 return access_from->IsInSamePackage(access_to);
379}
380
381jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) {
382 Class* c = Decode<Class*>(env, javaThis);
383 if (c->IsPrimitive() || c->IsInterface() || c->IsArrayClass() || c->IsAbstract()) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700384 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700385 "Class %s can not be instantiated", PrettyDescriptor(c->GetDescriptor()).c_str());
386 return NULL;
387 }
388
Elliott Hughes2a20cfd2011-09-23 19:30:41 -0700389 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
390 return NULL;
391 }
392
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700393 Method* init = c->FindDirectMethod("<init>", "()V");
394 if (init == NULL) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700395 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700396 "Class %s has no default <init>()V constructor", PrettyDescriptor(c->GetDescriptor()).c_str());
397 return NULL;
398 }
399
400 // Verify access from the call site.
401 //
402 // First, make sure the method invoking Class.newInstance() has permission
403 // to access the class.
404 //
405 // Second, make sure it has permission to invoke the constructor. The
406 // constructor must be public or, if the caller is in the same package,
407 // have package scope.
408 // TODO: need SmartFrame (Thread::WalkStack-like iterator).
409 Frame frame = Thread::Current()->GetTopOfStack();
410 frame.Next();
411 frame.Next();
412 Method* caller_caller = frame.GetMethod();
413 Class* caller_class = caller_caller->GetDeclaringClass();
414
Brian Carlstrombc2f3e32011-09-22 17:16:54 -0700415 if (!caller_class->CanAccess(c)) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700416 Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
417 "Class %s is not accessible from class %s",
418 PrettyDescriptor(c->GetDescriptor()).c_str(),
419 PrettyDescriptor(caller_class->GetDescriptor()).c_str());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700420 return NULL;
421 }
422 if (!CheckMemberAccess(caller_class, init->GetDeclaringClass(), init->GetAccessFlags())) {
Elliott Hughes5cb5ad22011-10-02 12:13:39 -0700423 Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalAccessException;",
424 "%s is not accessible from class %s",
425 PrettyMethod(init).c_str(),
426 PrettyDescriptor(caller_class->GetDescriptor()).c_str());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700427 return NULL;
428 }
429
430 Object* new_obj = c->AllocObject();
431 if (new_obj == NULL) {
432 DCHECK(Thread::Current()->IsExceptionPending());
433 return NULL;
434 }
435
436 // invoke constructor; unlike reflection calls, we don't wrap exceptions
437 jclass jklass = AddLocalReference<jclass>(env, c);
438 jmethodID mid = EncodeMethod(init);
439 return env->NewObject(jklass, mid);
440}
441
Elliott Hughesd369bb72011-09-12 14:41:14 -0700442static JNINativeMethod gMethods[] = {
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700443 NATIVE_METHOD(Class, classForName, "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700444 NATIVE_METHOD(Class, desiredAssertionStatus, "()Z"),
445 NATIVE_METHOD(Class, getClassLoader, "(Ljava/lang/Class;)Ljava/lang/ClassLoader;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700446 NATIVE_METHOD(Class, getComponentType, "()Ljava/lang/Class;"),
Brian Carlstrom3a7b4f22011-09-17 15:01:57 -0700447 NATIVE_METHOD(Class, getDeclaredConstructorOrMethod, "(Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Member;"),
Elliott Hughes80609252011-09-23 17:24:51 -0700448 NATIVE_METHOD(Class, getDeclaredConstructors, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;"),
Brian Carlstromf867b6f2011-09-16 12:17:25 -0700449 NATIVE_METHOD(Class, getDeclaredField, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field;"),
Elliott Hughes80609252011-09-23 17:24:51 -0700450 NATIVE_METHOD(Class, getDeclaredFields, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;"),
451 NATIVE_METHOD(Class, getDeclaredMethods, "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700452 NATIVE_METHOD(Class, getDeclaringClass, "()Ljava/lang/Class;"),
Jesse Wilson6bf19152011-09-29 13:12:33 -0400453 NATIVE_METHOD(Class, getDex, "()Lcom/android/dex/Dex;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700454 //NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"),
Elliott Hughes9dcc79d2011-10-02 16:31:10 -0700455 NATIVE_METHOD(Class, getModifiers, "(Ljava/lang/Class;Z)I"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700456 NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700457 NATIVE_METHOD(Class, getSuperclass, "()Ljava/lang/Class;"),
458 NATIVE_METHOD(Class, isAnonymousClass, "()Z"),
Elliott Hughesdd8df692011-09-23 14:42:41 -0700459 NATIVE_METHOD(Class, isAssignableFrom, "(Ljava/lang/Class;)Z"),
460 NATIVE_METHOD(Class, isInstance, "(Ljava/lang/Object;)Z"),
Elliott Hughes6bdc3b22011-09-16 19:24:10 -0700461 NATIVE_METHOD(Class, isInterface, "()Z"),
462 NATIVE_METHOD(Class, isPrimitive, "()Z"),
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700463 NATIVE_METHOD(Class, newInstanceImpl, "()Ljava/lang/Object;"),
Elliott Hughesd369bb72011-09-12 14:41:14 -0700464};
465
466} // namespace
467
468void register_java_lang_Class(JNIEnv* env) {
469 jniRegisterNativeMethods(env, "java/lang/Class", gMethods, NELEM(gMethods));
470}
471
472} // namespace art