blob: bed89d6472e0c471725292f7280b3e19a5585461 [file] [log] [blame]
Elliott Hughes64bf5a32011-09-20 14:43:12 -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 "class_linker.h"
18#include "jni_internal.h"
19#include "ScopedUtfChars.h"
20#include "zip_archive.h"
21
22#include "JniConstants.h" // Last to avoid problems with LOG redefinition.
23
24namespace art {
25
26namespace {
27
28// Turn "java.lang.String" into "Ljava/lang/String;".
29std::string ToDescriptor(const char* class_name) {
30 std::string descriptor(class_name);
31 std::replace(descriptor.begin(), descriptor.end(), '.', '/');
32 if (descriptor.length() > 0 && descriptor[0] != '[') {
33 descriptor = "L" + descriptor + ";";
34 }
35 return descriptor;
36}
37
38jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader, jstring javaName) {
39 ClassLoader* loader = Decode<ClassLoader*>(env, javaLoader);
40 ScopedUtfChars name(env, javaName);
41 if (name.c_str() == NULL) {
42 return NULL;
43 }
44
45 std::string descriptor(ToDescriptor(name.c_str()));
46 Class* c = Runtime::Current()->GetClassLinker()->LookupClass(descriptor.c_str(), loader);
47 return AddLocalReference<jclass>(env, c);
48}
49
50jint VMClassLoader_getBootClassPathSize(JNIEnv* env, jclass) {
51 return Runtime::Current()->GetClassLinker()->GetBootClassPath().size();
52}
53
54/*
55 * Returns a string URL for a resource with the specified 'javaName' in
56 * entry 'index' of the boot class path.
57 *
58 * We return a newly-allocated String in the following form:
59 *
60 * jar:file://path!/name
61 *
62 * Where "path" is the bootstrap class path entry and "name" is the string
63 * passed into this method. "path" needs to be an absolute path (starting
64 * with '/'); if it's not we'd need to make it absolute as part of forming
65 * the URL string.
66 */
67jstring VMClassLoader_getBootClassPathResource(JNIEnv* env, jclass, jstring javaName, jint index) {
68 ScopedUtfChars name(env, javaName);
69 if (name.c_str() == NULL) {
70 return NULL;
71 }
72
73 const std::vector<const DexFile*>& path = Runtime::Current()->GetClassLinker()->GetBootClassPath();
74 if (index < 0 || size_t(index) >= path.size()) {
75 return NULL;
76 }
77 const DexFile* dex_file = path[index];
78 const std::string& location(dex_file->GetLocation());
79 UniquePtr<ZipArchive> zip_archive(ZipArchive::Open(location));
80 if (zip_archive.get() == NULL) {
81 return NULL;
82 }
83 UniquePtr<ZipEntry> zip_entry(zip_archive->Find(name.c_str()));
84 if (zip_entry.get() == NULL) {
85 return NULL;
86 }
87
88 std::string url;
89 StringAppendF(&url, "jar:file://%s!/%s", location.c_str(), name.c_str());
90 return env->NewStringUTF(url.c_str());
91}
92
93/*
94 * static Class loadClass(String name, boolean resolve)
95 * throws ClassNotFoundException
96 *
97 * Load class using bootstrap class loader.
98 *
99 * Return the Class object associated with the class or interface with
100 * the specified name.
101 *
102 * "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
103 */
104jclass VMClassLoader_loadClass(JNIEnv* env, jclass, jstring javaName, jboolean resolve) {
105 ScopedUtfChars name(env, javaName);
106 if (name.c_str() == NULL) {
107 return NULL;
108 }
109
110 /*
111 * We need to validate and convert the name (from x.y.z to x/y/z). This
112 * is especially handy for array types, since we want to avoid
113 * auto-generating bogus array classes.
114 */
115 if (!IsValidClassName(name.c_str(), true, true)) {
116 Thread::Current()->ThrowNewException("Ljava/lang/ClassNotFoundException;",
117 "Invalid name: %s", name.c_str());
118 return NULL;
119 }
120
121 std::string descriptor(ToDescriptor(name.c_str()));
122 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
123 Class* c = class_linker->FindClass(descriptor.c_str(), NULL);
124 if (resolve) {
125 class_linker->EnsureInitialized(c, true);
126 }
127 return AddLocalReference<jclass>(env, c);
128}
129
130static JNINativeMethod gMethods[] = {
131 NATIVE_METHOD(VMClassLoader, findLoadedClass, "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;"),
132 NATIVE_METHOD(VMClassLoader, getBootClassPathResource, "(Ljava/lang/String;I)Ljava/lang/String;"),
133 NATIVE_METHOD(VMClassLoader, getBootClassPathSize, "()I"),
134 NATIVE_METHOD(VMClassLoader, loadClass, "(Ljava/lang/String;Z)Ljava/lang/Class;"),
135};
136
137} // namespace
138
139void register_java_lang_VMClassLoader(JNIEnv* env) {
140 jniRegisterNativeMethods(env, "java/lang/VMClassLoader", gMethods, NELEM(gMethods));
141}
142
143} // namespace art