blob: 37a524b66defb257d0fbb91b80d12e19b0c9bd4e [file] [log] [blame]
Brian Carlstromf91c8c32011-09-21 17:30:34 -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
Andreas Gampe277ccbd2014-11-03 21:36:10 -080017#include "dalvik_system_DexFile.h"
18
Narayan Kamath8943c1d2016-05-02 13:14:48 +010019#include <sstream>
20
Andreas Gampe46ee31b2016-12-14 10:11:49 -080021#include "android-base/stringprintf.h"
22
Vladimir Marko78baed52018-10-11 10:44:58 +010023#include "base/casts.h"
David Sehr891a50e2017-10-27 17:01:07 -070024#include "base/file_utils.h"
Andreas Gampeb74f3072019-05-01 15:19:00 -070025#include "base/hiddenapi_domain.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080026#include "base/logging.h"
David Sehrc431b9d2018-03-02 12:01:51 -080027#include "base/os.h"
Andreas Gampe833a4852014-05-21 18:46:59 -070028#include "base/stl_util.h"
David Sehrc431b9d2018-03-02 12:01:51 -080029#include "base/utils.h"
David Sehr79e26072018-04-06 17:58:50 -070030#include "base/zip_archive.h"
Brian Carlstromaded5f72011-10-07 17:15:04 -070031#include "class_linker.h"
David Brazdil74582912019-03-01 11:18:19 +000032#include "class_loader_context.h"
Ian Rogers62d6c772013-02-27 08:32:07 -080033#include "common_throws.h"
Andreas Gampec38be812016-03-23 15:03:46 -070034#include "compiler_filter.h"
David Sehr013fd802018-01-11 22:55:24 -080035#include "dex/art_dex_file_loader.h"
David Sehrb2ec9f52018-02-21 13:20:31 -080036#include "dex/descriptors_names.h"
David Sehr9e734c72018-01-04 17:56:19 -080037#include "dex/dex_file-inl.h"
38#include "dex/dex_file_loader.h"
Andreas Gampe88dbad32018-06-26 19:54:12 -070039#include "handle_scope-inl.h"
David Srbeckyfb3de3d2018-01-29 16:11:49 +000040#include "jit/debugger_interface.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010041#include "jni/jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080042#include "mirror/class_loader.h"
Ian Rogers05f30572013-02-20 12:13:11 -080043#include "mirror/object-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080044#include "mirror/string.h"
Andreas Gampe87583b32017-05-25 11:22:18 -070045#include "native_util.h"
Steven Morelande431e272017-07-18 16:53:49 -070046#include "nativehelper/jni_macros.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070047#include "nativehelper/scoped_local_ref.h"
48#include "nativehelper/scoped_utf_chars.h"
Narayan Kamath8943c1d2016-05-02 13:14:48 +010049#include "oat_file.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080050#include "oat_file_assistant.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070051#include "oat_file_manager.h"
Brian Carlstromaded5f72011-10-07 17:15:04 -070052#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070053#include "scoped_thread_state_change-inl.h"
Ian Rogersdd157d72014-05-15 14:47:50 -070054#include "well_known_classes.h"
Brian Carlstromf91c8c32011-09-21 17:30:34 -070055
56namespace art {
57
Andreas Gampe46ee31b2016-12-14 10:11:49 -080058using android::base::StringPrintf;
59
Mathieu Chartiere58991b2015-10-13 07:59:34 -070060static bool ConvertJavaArrayToDexFiles(
61 JNIEnv* env,
62 jobject arrayObject,
63 /*out*/ std::vector<const DexFile*>& dex_files,
64 /*out*/ const OatFile*& oat_file) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -080065 jarray array = reinterpret_cast<jarray>(arrayObject);
66
67 jsize array_size = env->GetArrayLength(array);
68 if (env->ExceptionCheck() == JNI_TRUE) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -070069 return false;
Andreas Gampe324b9bb2015-02-23 16:33:22 -080070 }
71
72 // TODO: Optimize. On 32bit we can use an int array.
73 jboolean is_long_data_copied;
74 jlong* long_data = env->GetLongArrayElements(reinterpret_cast<jlongArray>(array),
75 &is_long_data_copied);
76 if (env->ExceptionCheck() == JNI_TRUE) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -070077 return false;
Andreas Gampe324b9bb2015-02-23 16:33:22 -080078 }
79
Vladimir Marko78baed52018-10-11 10:44:58 +010080 oat_file = reinterpret_cast64<const OatFile*>(long_data[kOatFileIndex]);
Mathieu Chartiere58991b2015-10-13 07:59:34 -070081 dex_files.reserve(array_size - 1);
82 for (jsize i = kDexFileIndexStart; i < array_size; ++i) {
Vladimir Marko78baed52018-10-11 10:44:58 +010083 dex_files.push_back(reinterpret_cast64<const DexFile*>(long_data[i]));
Andreas Gampe324b9bb2015-02-23 16:33:22 -080084 }
85
86 env->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), long_data, JNI_ABORT);
Mathieu Chartiere58991b2015-10-13 07:59:34 -070087 return env->ExceptionCheck() != JNI_TRUE;
Andreas Gampe324b9bb2015-02-23 16:33:22 -080088}
89
Mathieu Chartiere58991b2015-10-13 07:59:34 -070090static jlongArray ConvertDexFilesToJavaArray(JNIEnv* env,
91 const OatFile* oat_file,
92 std::vector<std::unique_ptr<const DexFile>>& vec) {
93 // Add one for the oat file.
Mathieu Chartier80b37b72015-10-12 18:13:39 -070094 jlongArray long_array = env->NewLongArray(static_cast<jsize>(kDexFileIndexStart + vec.size()));
Andreas Gampe324b9bb2015-02-23 16:33:22 -080095 if (env->ExceptionCheck() == JNI_TRUE) {
96 return nullptr;
97 }
98
99 jboolean is_long_data_copied;
100 jlong* long_data = env->GetLongArrayElements(long_array, &is_long_data_copied);
101 if (env->ExceptionCheck() == JNI_TRUE) {
102 return nullptr;
103 }
104
Vladimir Marko78baed52018-10-11 10:44:58 +0100105 long_data[kOatFileIndex] = reinterpret_cast64<jlong>(oat_file);
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700106 for (size_t i = 0; i < vec.size(); ++i) {
Vladimir Marko78baed52018-10-11 10:44:58 +0100107 long_data[kDexFileIndexStart + i] = reinterpret_cast64<jlong>(vec[i].get());
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800108 }
109
110 env->ReleaseLongArrayElements(long_array, long_data, 0);
111 if (env->ExceptionCheck() == JNI_TRUE) {
112 return nullptr;
113 }
114
115 // Now release all the unique_ptrs.
116 for (auto& dex_file : vec) {
Andreas Gampeafaf7f82018-10-16 11:32:38 -0700117 dex_file.release(); // NOLINT
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800118 }
119
120 return long_array;
121}
122
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700123// A smart pointer that provides read-only access to a Java string's UTF chars.
124// Unlike libcore's NullableScopedUtfChars, this will *not* throw NullPointerException if
125// passed a null jstring. The correct idiom is:
126//
127// NullableScopedUtfChars name(env, javaName);
Brian Carlstromc252c3e2011-10-16 23:21:02 -0700128// if (env->ExceptionCheck()) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700129// return null;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700130// }
131// // ... use name.c_str()
132//
133// TODO: rewrite to get rid of this, or change ScopedUtfChars to offer this option.
134class NullableScopedUtfChars {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800135 public:
136 NullableScopedUtfChars(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700137 mUtfChars = (s != nullptr) ? env->GetStringUTFChars(s, nullptr) : nullptr;
Elliott Hughesba8eee12012-01-24 20:25:24 -0800138 }
139
140 ~NullableScopedUtfChars() {
141 if (mUtfChars) {
142 mEnv->ReleaseStringUTFChars(mString, mUtfChars);
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700143 }
Elliott Hughesba8eee12012-01-24 20:25:24 -0800144 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700145
Elliott Hughesba8eee12012-01-24 20:25:24 -0800146 const char* c_str() const {
147 return mUtfChars;
148 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700149
Elliott Hughesba8eee12012-01-24 20:25:24 -0800150 size_t size() const {
151 return strlen(mUtfChars);
152 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700153
Elliott Hughesba8eee12012-01-24 20:25:24 -0800154 // Element access.
155 const char& operator[](size_t n) const {
156 return mUtfChars[n];
157 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700158
Elliott Hughesba8eee12012-01-24 20:25:24 -0800159 private:
160 JNIEnv* mEnv;
161 jstring mString;
162 const char* mUtfChars;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700163
Elliott Hughesba8eee12012-01-24 20:25:24 -0800164 // Disallow copy and assignment.
165 NullableScopedUtfChars(const NullableScopedUtfChars&);
166 void operator=(const NullableScopedUtfChars&);
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700167};
168
David Brazdil7126c5b2019-03-05 00:02:51 +0000169static jobject CreateCookieFromOatFileManagerResult(
170 JNIEnv* env,
171 std::vector<std::unique_ptr<const DexFile>>& dex_files,
172 const OatFile* oat_file,
173 const std::vector<std::string>& error_msgs) {
174 ClassLinker* linker = Runtime::Current()->GetClassLinker();
175 if (dex_files.empty()) {
176 ScopedObjectAccess soa(env);
177 CHECK(!error_msgs.empty());
178 // The most important message is at the end. So set up nesting by going forward, which will
179 // wrap the existing exception as a cause for the following one.
180 auto it = error_msgs.begin();
181 auto itEnd = error_msgs.end();
182 for ( ; it != itEnd; ++it) {
183 ThrowWrappedIOException("%s", it->c_str());
184 }
185 return nullptr;
186 }
187
188 jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files);
189 if (array == nullptr) {
190 ScopedObjectAccess soa(env);
191 for (auto& dex_file : dex_files) {
192 if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
193 dex_file.release(); // NOLINT
194 }
195 }
196 }
197 return array;
198}
199
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100200static MemMap AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) {
Alex Lightea9465e2017-02-16 15:38:35 -0800201 if (end <= start) {
202 ScopedObjectAccess soa(env);
203 ThrowWrappedIOException("Bad range");
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100204 return MemMap::Invalid();
Alex Lightea9465e2017-02-16 15:38:35 -0800205 }
206
207 std::string error_message;
208 size_t length = static_cast<size_t>(end - start);
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100209 MemMap dex_mem_map = MemMap::MapAnonymous("DEX data",
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100210 length,
211 PROT_READ | PROT_WRITE,
Vladimir Marko11306592018-10-26 14:22:59 +0100212 /*low_4gb=*/ false,
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100213 &error_message);
214 if (!dex_mem_map.IsValid()) {
Alex Lightea9465e2017-02-16 15:38:35 -0800215 ScopedObjectAccess soa(env);
216 ThrowWrappedIOException("%s", error_message.c_str());
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100217 return MemMap::Invalid();
Alex Lightea9465e2017-02-16 15:38:35 -0800218 }
219 return dex_mem_map;
220}
221
David Brazdil74582912019-03-01 11:18:19 +0000222struct ScopedIntArrayAccessor {
223 public:
224 ScopedIntArrayAccessor(JNIEnv* env, jintArray arr) : env_(env), array_(arr) {
225 elements_ = env_->GetIntArrayElements(array_, /* isCopy= */ nullptr);
226 CHECK(elements_ != nullptr);
Alex Lightea9465e2017-02-16 15:38:35 -0800227 }
David Brazdil74582912019-03-01 11:18:19 +0000228
229 ~ScopedIntArrayAccessor() {
230 env_->ReleaseIntArrayElements(array_, elements_, JNI_ABORT);
231 }
232
233 jint Get(jsize index) const { return elements_[index]; }
234
235 private:
236 JNIEnv* env_;
237 jintArray array_;
238 jint* elements_;
239};
240
241static jobject DexFile_openInMemoryDexFilesNative(JNIEnv* env,
242 jclass,
243 jobjectArray buffers,
244 jobjectArray arrays,
245 jintArray jstarts,
David Brazdil7126c5b2019-03-05 00:02:51 +0000246 jintArray jends,
247 jobject class_loader,
248 jobjectArray dex_elements) {
David Brazdil74582912019-03-01 11:18:19 +0000249 jsize buffers_length = env->GetArrayLength(buffers);
250 CHECK_EQ(buffers_length, env->GetArrayLength(arrays));
251 CHECK_EQ(buffers_length, env->GetArrayLength(jstarts));
252 CHECK_EQ(buffers_length, env->GetArrayLength(jends));
253
254 ScopedIntArrayAccessor starts(env, jstarts);
255 ScopedIntArrayAccessor ends(env, jends);
256
257 // Allocate memory for dex files and copy data from ByteBuffers.
David Brazdil7126c5b2019-03-05 00:02:51 +0000258 std::vector<MemMap> dex_mem_maps;
259 dex_mem_maps.reserve(buffers_length);
David Brazdil74582912019-03-01 11:18:19 +0000260 for (jsize i = 0; i < buffers_length; ++i) {
261 jobject buffer = env->GetObjectArrayElement(buffers, i);
262 jbyteArray array = reinterpret_cast<jbyteArray>(env->GetObjectArrayElement(arrays, i));
263 jint start = starts.Get(i);
264 jint end = ends.Get(i);
Alex Lightea9465e2017-02-16 15:38:35 -0800265
David Brazdil74582912019-03-01 11:18:19 +0000266 MemMap dex_data = AllocateDexMemoryMap(env, start, end);
267 if (!dex_data.IsValid()) {
268 DCHECK(Thread::Current()->IsExceptionPending());
269 return nullptr;
270 }
271
272 if (array == nullptr) {
273 // Direct ByteBuffer
274 uint8_t* base_address = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
275 if (base_address == nullptr) {
276 ScopedObjectAccess soa(env);
277 ThrowWrappedIOException("dexFileBuffer not direct");
278 return nullptr;
279 }
280 size_t length = static_cast<size_t>(end - start);
281 memcpy(dex_data.Begin(), base_address + start, length);
282 } else {
283 // ByteBuffer backed by a byte array
284 jbyte* destination = reinterpret_cast<jbyte*>(dex_data.Begin());
285 env->GetByteArrayRegion(array, start, end - start, destination);
286 }
287
David Brazdil7126c5b2019-03-05 00:02:51 +0000288 dex_mem_maps.push_back(std::move(dex_data));
Alex Lightea9465e2017-02-16 15:38:35 -0800289 }
290
David Brazdil7126c5b2019-03-05 00:02:51 +0000291 // Hand MemMaps over to OatFileManager to open the dex files and potentially
292 // create a backing OatFile instance from an anonymous vdex.
293 std::vector<std::string> error_msgs;
294 const OatFile* oat_file = nullptr;
295 std::vector<std::unique_ptr<const DexFile>> dex_files =
296 Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(std::move(dex_mem_maps),
297 class_loader,
298 dex_elements,
299 /*out*/ &oat_file,
300 /*out*/ &error_msgs);
301 return CreateCookieFromOatFileManagerResult(env, dex_files, oat_file, error_msgs);
Alex Lightea9465e2017-02-16 15:38:35 -0800302}
303
Calin Juravle1f7079b2017-04-18 21:25:37 -0700304// TODO(calin): clean up the unused parameters (here and in libcore).
Mathieu Chartierb190d942015-11-12 10:00:58 -0800305static jobject DexFile_openDexFileNative(JNIEnv* env,
306 jclass,
307 jstring javaSourceName,
Calin Juravle1f7079b2017-04-18 21:25:37 -0700308 jstring javaOutputName ATTRIBUTE_UNUSED,
Mathieu Chartierb190d942015-11-12 10:00:58 -0800309 jint flags ATTRIBUTE_UNUSED,
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800310 jobject class_loader,
311 jobjectArray dex_elements) {
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700312 ScopedUtfChars sourceName(env, javaSourceName);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700313 if (sourceName.c_str() == nullptr) {
Yi Kong4b22b342018-08-02 14:43:21 -0700314 return nullptr;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700315 }
Calin Juravle1f7079b2017-04-18 21:25:37 -0700316
Andreas Gampe833a4852014-05-21 18:46:59 -0700317 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700318 const OatFile* oat_file = nullptr;
David Brazdil7126c5b2019-03-05 00:02:51 +0000319 std::vector<std::unique_ptr<const DexFile>> dex_files =
320 Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
321 class_loader,
322 dex_elements,
323 /*out*/ &oat_file,
324 /*out*/ &error_msgs);
325 return CreateCookieFromOatFileManagerResult(env, dex_files, oat_file, error_msgs);
Brian Carlstromaded5f72011-10-07 17:15:04 -0700326}
327
David Brazdil35a3f6a2019-03-04 15:59:06 +0000328static jstring DexFile_getClassLoaderContext(JNIEnv* env,
329 jclass,
330 jobject class_loader,
331 jobjectArray dex_elements) {
332 CHECK(class_loader != nullptr);
333 constexpr const char* kBaseDir = "";
334 std::unique_ptr<ClassLoaderContext> context =
335 ClassLoaderContext::CreateContextForClassLoader(class_loader, dex_elements);
336 if (context == nullptr || !context->OpenDexFiles(kRuntimeISA, kBaseDir)) {
337 LOG(WARNING) << "Could not establish class loader context";
338 return nullptr;
339 }
340 std::string str_context = context->EncodeContextForOatFile(kBaseDir);
341 return env->NewStringUTF(str_context.c_str());
342}
343
David Brazdil331a5e12019-04-01 22:46:16 +0000344static void DexFile_verifyInBackgroundNative(JNIEnv* env,
345 jclass,
346 jobject cookie,
David Brazdil35a3f6a2019-03-04 15:59:06 +0000347 jobject class_loader,
348 jstring class_loader_context) {
David Brazdil331a5e12019-04-01 22:46:16 +0000349 CHECK(cookie != nullptr);
350 CHECK(class_loader != nullptr);
351
352 // Extract list of dex files from the cookie.
353 std::vector<const DexFile*> dex_files;
354 const OatFile* oat_file;
355 if (!ConvertJavaArrayToDexFiles(env, cookie, dex_files, oat_file)) {
356 Thread::Current()->AssertPendingException();
357 return;
358 }
359 CHECK(oat_file == nullptr) << "Called verifyInBackground on a dex file backed by oat";
360
David Brazdil35a3f6a2019-03-04 15:59:06 +0000361 ScopedUtfChars class_loader_context_utf(env, class_loader_context);
362 if (env->ExceptionCheck()) {
363 LOG(ERROR) << "Failed to unwrap class loader context string";
364 return;
365 }
366
David Brazdil331a5e12019-04-01 22:46:16 +0000367 // Hand over to OatFileManager to spawn a verification thread.
David Brazdil35a3f6a2019-03-04 15:59:06 +0000368 Runtime::Current()->GetOatFileManager().RunBackgroundVerification(
369 dex_files,
370 class_loader,
371 class_loader_context_utf.c_str());
David Brazdil331a5e12019-04-01 22:46:16 +0000372}
373
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700374static jboolean DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700375 std::vector<const DexFile*> dex_files;
376 const OatFile* oat_file;
377 if (!ConvertJavaArrayToDexFiles(env, cookie, dex_files, oat_file)) {
378 Thread::Current()->AssertPendingException();
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700379 return JNI_FALSE;
380 }
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700381 Runtime* const runtime = Runtime::Current();
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700382 bool all_deleted = true;
David Srbecky912f36c2018-09-08 12:22:58 +0100383 // We need to clear the caches since they may contain pointers to the dex instructions.
384 // Different dex file can be loaded at the same memory location later by chance.
385 Thread::ClearAllInterpreterCaches();
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700386 {
387 ScopedObjectAccess soa(env);
Mathieu Chartier0795f232016-09-27 18:43:30 -0700388 ObjPtr<mirror::Object> dex_files_object = soa.Decode<mirror::Object>(cookie);
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700389 ObjPtr<mirror::LongArray> long_dex_files = dex_files_object->AsLongArray();
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700390 // Delete dex files associated with this dalvik.system.DexFile since there should not be running
391 // code using it. dex_files is a vector due to multidex.
392 ClassLinker* const class_linker = runtime->GetClassLinker();
393 int32_t i = kDexFileIndexStart; // Oat file is at index 0.
394 for (const DexFile* dex_file : dex_files) {
395 if (dex_file != nullptr) {
David Srbeckyafc60cd2018-12-05 11:59:31 +0000396 RemoveNativeDebugInfoForDex(soa.Self(), dex_file);
David Brazdil74582912019-03-01 11:18:19 +0000397 // Only delete the dex file if the dex cache is not found to prevent runtime crashes
398 // if there are calls to DexFile.close while the ART DexFile is still in use.
Vladimir Markocd556b02017-02-03 11:47:34 +0000399 if (!class_linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700400 // Clear the element in the array so that we can call close again.
401 long_dex_files->Set(i, 0);
402 delete dex_file;
403 } else {
404 all_deleted = false;
405 }
406 }
407 ++i;
Andreas Gampe833a4852014-05-21 18:46:59 -0700408 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700409 }
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700410
Mathieu Chartierfdccbd42015-10-14 10:58:41 -0700411 // oat_file can be null if we are running without dex2oat.
412 if (all_deleted && oat_file != nullptr) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700413 // If all of the dex files are no longer in use we can unmap the corresponding oat file.
414 VLOG(class_linker) << "Unregistering " << oat_file;
415 runtime->GetOatFileManager().UnRegisterAndDeleteOatFile(oat_file);
416 }
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700417 return all_deleted ? JNI_TRUE : JNI_FALSE;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700418}
419
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700420static jclass DexFile_defineClassNative(JNIEnv* env,
421 jclass,
422 jstring javaName,
423 jobject javaLoader,
Mathieu Chartier00310e02015-10-17 12:46:42 -0700424 jobject cookie,
425 jobject dexFile) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700426 std::vector<const DexFile*> dex_files;
427 const OatFile* oat_file;
428 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out*/ dex_files, /*out*/ oat_file)) {
Brian Carlstrom7571e8b2013-08-12 17:04:14 -0700429 VLOG(class_linker) << "Failed to find dex_file";
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800430 DCHECK(env->ExceptionCheck());
431 return nullptr;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700432 }
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800433
Brian Carlstromdf143242011-10-10 18:05:34 -0700434 ScopedUtfChars class_name(env, javaName);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700435 if (class_name.c_str() == nullptr) {
Brian Carlstrom2e450bf2013-09-06 15:39:46 -0700436 VLOG(class_linker) << "Failed to find class_name";
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700437 return nullptr;
Brian Carlstromdf143242011-10-10 18:05:34 -0700438 }
Elliott Hughes95572412011-12-13 18:14:20 -0800439 const std::string descriptor(DotToDescriptor(class_name.c_str()));
Mathieu Chartiere7c9a8c2014-11-06 16:35:45 -0800440 const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str()));
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700441 for (auto& dex_file : dex_files) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800442 const dex::ClassDef* dex_class_def =
David Sehr9aa352e2016-09-15 18:13:52 -0700443 OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash);
Andreas Gampe833a4852014-05-21 18:46:59 -0700444 if (dex_class_def != nullptr) {
445 ScopedObjectAccess soa(env);
446 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Andreas Gampe833a4852014-05-21 18:46:59 -0700447 StackHandleScope<1> hs(soa.Self());
448 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700449 hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
Vladimir Markocd556b02017-02-03 11:47:34 +0000450 ObjPtr<mirror::DexCache> dex_cache =
451 class_linker->RegisterDexFile(*dex_file, class_loader.Get());
452 if (dex_cache == nullptr) {
453 // OOME or InternalError (dexFile already registered with a different class loader).
454 soa.Self()->AssertPendingException();
455 return nullptr;
456 }
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700457 ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(),
458 descriptor.c_str(),
459 hash,
460 class_loader,
461 *dex_file,
462 *dex_class_def);
Mathieu Chartier00310e02015-10-17 12:46:42 -0700463 // Add the used dex file. This only required for the DexFile.loadClass API since normal
464 // class loaders already keep their dex files live.
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700465 class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile),
Mathieu Chartier00310e02015-10-17 12:46:42 -0700466 class_loader.Get());
Andreas Gampe833a4852014-05-21 18:46:59 -0700467 if (result != nullptr) {
Brian Carlstrom667ab7c2014-10-16 19:12:28 -0700468 VLOG(class_linker) << "DexFile_defineClassNative returning " << result
469 << " for " << class_name.c_str();
Andreas Gampe833a4852014-05-21 18:46:59 -0700470 return soa.AddLocalReference<jclass>(result);
471 }
472 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700473 }
Brian Carlstrom667ab7c2014-10-16 19:12:28 -0700474 VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str();
Andreas Gampe833a4852014-05-21 18:46:59 -0700475 return nullptr;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700476}
477
Andreas Gampe833a4852014-05-21 18:46:59 -0700478// Needed as a compare functor for sets of const char
479struct CharPointerComparator {
480 bool operator()(const char *str1, const char *str2) const {
481 return strcmp(str1, str2) < 0;
482 }
483};
484
485// Note: this can be an expensive call, as we sort out duplicates in MultiDex files.
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800486static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jobject cookie) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700487 const OatFile* oat_file = nullptr;
488 std::vector<const DexFile*> dex_files;
489 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800490 DCHECK(env->ExceptionCheck());
491 return nullptr;
492 }
Andreas Gampe833a4852014-05-21 18:46:59 -0700493
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800494 // Push all class descriptors into a set. Use set instead of unordered_set as we want to
495 // retrieve all in the end.
496 std::set<const char*, CharPointerComparator> descriptors;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700497 for (auto& dex_file : dex_files) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800498 for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800499 const dex::ClassDef& class_def = dex_file->GetClassDef(i);
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800500 const char* descriptor = dex_file->GetClassDescriptor(class_def);
501 descriptors.insert(descriptor);
Andreas Gampe833a4852014-05-21 18:46:59 -0700502 }
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800503 }
Andreas Gampe833a4852014-05-21 18:46:59 -0700504
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800505 // Now create output array and copy the set into it.
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700506 jobjectArray result = env->NewObjectArray(descriptors.size(),
507 WellKnownClasses::java_lang_String,
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800508 nullptr);
509 if (result != nullptr) {
510 auto it = descriptors.begin();
511 auto it_end = descriptors.end();
512 jsize i = 0;
513 for (; it != it_end; it++, ++i) {
514 std::string descriptor(DescriptorToDot(*it));
515 ScopedLocalRef<jstring> jdescriptor(env, env->NewStringUTF(descriptor.c_str()));
516 if (jdescriptor.get() == nullptr) {
517 return nullptr;
Ian Rogersdd157d72014-05-15 14:47:50 -0700518 }
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800519 env->SetObjectArrayElement(result, i, jdescriptor.get());
Ian Rogersdd157d72014-05-15 14:47:50 -0700520 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700521 }
Ian Rogersdd157d72014-05-15 14:47:50 -0700522 return result;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700523}
524
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700525static jint GetDexOptNeeded(JNIEnv* env,
526 const char* filename,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700527 const char* instruction_set,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000528 const char* compiler_filter_name,
Calin Juravle20c46442017-09-12 00:54:26 -0700529 const char* class_loader_context,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700530 bool profile_changed,
531 bool downgrade) {
Narayan Kamath11d9f062014-04-23 20:24:57 +0100532 if ((filename == nullptr) || !OS::FileExists(filename)) {
Richard Uhler95abd042015-03-24 09:51:28 -0700533 LOG(ERROR) << "DexFile_getDexOptNeeded file '" << filename << "' does not exist";
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700534 ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
Narayan Kamath11d9f062014-04-23 20:24:57 +0100535 const char* message = (filename == nullptr) ? "<empty file name>" : filename;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700536 env->ThrowNew(fnfe.get(), message);
Calin Juravleb077e152016-02-18 18:47:37 +0000537 return -1;
Brian Carlstrom1d9f52b2011-10-13 10:50:45 -0700538 }
539
Alex Light6e183f22014-07-18 14:57:04 -0700540 const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set);
Vladimir Marko33bff252017-11-01 14:35:42 +0000541 if (target_instruction_set == InstructionSet::kNone) {
Andreas Gampe20c89302014-08-19 17:28:06 -0700542 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
543 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set));
544 env->ThrowNew(iae.get(), message.c_str());
Calin Juravleb077e152016-02-18 18:47:37 +0000545 return -1;
Andreas Gampe20c89302014-08-19 17:28:06 -0700546 }
Alex Light6e183f22014-07-18 14:57:04 -0700547
Andreas Gampe29d38e72016-03-23 15:31:51 +0000548 CompilerFilter::Filter filter;
549 if (!CompilerFilter::ParseCompilerFilter(compiler_filter_name, &filter)) {
550 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
551 std::string message(StringPrintf("Compiler filter %s is invalid.", compiler_filter_name));
552 env->ThrowNew(iae.get(), message.c_str());
553 return -1;
554 }
555
Calin Juravle20c46442017-09-12 00:54:26 -0700556 std::unique_ptr<ClassLoaderContext> context = nullptr;
557 if (class_loader_context != nullptr) {
558 context = ClassLoaderContext::Create(class_loader_context);
559
560 if (context == nullptr) {
561 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
562 std::string message(StringPrintf("Class loader context '%s' is invalid.",
563 class_loader_context));
564 env->ThrowNew(iae.get(), message.c_str());
565 return -1;
566 }
567 }
568
Richard Uhler66d874d2015-01-15 09:37:19 -0800569 // TODO: Verify the dex location is well formed, and throw an IOException if
570 // not?
Andreas Gampe29d38e72016-03-23 15:31:51 +0000571
Richard Uhlerd1472a22016-04-15 15:18:56 -0700572 OatFileAssistant oat_file_assistant(filename, target_instruction_set, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800573
574 // Always treat elements of the bootclasspath as up-to-date.
575 if (oat_file_assistant.IsInBootClassPath()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700576 return OatFileAssistant::kNoDexOptNeeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800577 }
Calin Juravle44e5efa2017-09-12 00:54:26 -0700578
Calin Juravle20c46442017-09-12 00:54:26 -0700579 return oat_file_assistant.GetDexOptNeeded(filter,
580 profile_changed,
581 downgrade,
582 context.get());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700583}
584
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100585static jstring DexFile_getDexFileStatus(JNIEnv* env,
586 jclass,
587 jstring javaFilename,
588 jstring javaInstructionSet) {
589 ScopedUtfChars filename(env, javaFilename);
590 if (env->ExceptionCheck()) {
591 return nullptr;
592 }
593
594 ScopedUtfChars instruction_set(env, javaInstructionSet);
595 if (env->ExceptionCheck()) {
596 return nullptr;
597 }
598
599 const InstructionSet target_instruction_set = GetInstructionSetFromString(
600 instruction_set.c_str());
Vladimir Marko33bff252017-11-01 14:35:42 +0000601 if (target_instruction_set == InstructionSet::kNone) {
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100602 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
603 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
604 env->ThrowNew(iae.get(), message.c_str());
605 return nullptr;
606 }
607
608 OatFileAssistant oat_file_assistant(filename.c_str(), target_instruction_set,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700609 /* load_executable= */ false);
Richard Uhler46cc64f2016-11-14 14:53:55 +0000610 return env->NewStringUTF(oat_file_assistant.GetStatusDump().c_str());
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100611}
612
Calin Juravle5f9a8012018-02-12 20:27:46 -0800613// Return an array specifying the optimization status of the given file.
614// The array specification is [compiler_filter, compiler_reason].
615static jobjectArray DexFile_getDexFileOptimizationStatus(JNIEnv* env,
616 jclass,
617 jstring javaFilename,
618 jstring javaInstructionSet) {
619 ScopedUtfChars filename(env, javaFilename);
620 if (env->ExceptionCheck()) {
621 return nullptr;
622 }
623
624 ScopedUtfChars instruction_set(env, javaInstructionSet);
625 if (env->ExceptionCheck()) {
626 return nullptr;
627 }
628
629 const InstructionSet target_instruction_set = GetInstructionSetFromString(
630 instruction_set.c_str());
631 if (target_instruction_set == InstructionSet::kNone) {
632 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
633 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
634 env->ThrowNew(iae.get(), message.c_str());
635 return nullptr;
636 }
637
638 std::string compilation_filter;
639 std::string compilation_reason;
640 OatFileAssistant::GetOptimizationStatus(
641 filename.c_str(), target_instruction_set, &compilation_filter, &compilation_reason);
642
643 ScopedLocalRef<jstring> j_compilation_filter(env, env->NewStringUTF(compilation_filter.c_str()));
644 if (j_compilation_filter.get() == nullptr) {
645 return nullptr;
646 }
647 ScopedLocalRef<jstring> j_compilation_reason(env, env->NewStringUTF(compilation_reason.c_str()));
648 if (j_compilation_reason.get() == nullptr) {
649 return nullptr;
650 }
651
652 // Now create output array and copy the set into it.
653 jobjectArray result = env->NewObjectArray(2,
654 WellKnownClasses::java_lang_String,
655 nullptr);
656 env->SetObjectArrayElement(result, 0, j_compilation_filter.get());
657 env->SetObjectArrayElement(result, 1, j_compilation_reason.get());
658
659 return result;
660}
661
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700662static jint DexFile_getDexOptNeeded(JNIEnv* env,
663 jclass,
664 jstring javaFilename,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700665 jstring javaInstructionSet,
Andreas Gampec38be812016-03-23 15:03:46 -0700666 jstring javaTargetCompilerFilter,
Calin Juravle20c46442017-09-12 00:54:26 -0700667 jstring javaClassLoaderContext,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700668 jboolean newProfile,
669 jboolean downgrade) {
Narayan Kamath11d9f062014-04-23 20:24:57 +0100670 ScopedUtfChars filename(env, javaFilename);
Andreas Gampe20c89302014-08-19 17:28:06 -0700671 if (env->ExceptionCheck()) {
Calin Juravleb077e152016-02-18 18:47:37 +0000672 return -1;
Andreas Gampe20c89302014-08-19 17:28:06 -0700673 }
674
Narayan Kamath11d9f062014-04-23 20:24:57 +0100675 ScopedUtfChars instruction_set(env, javaInstructionSet);
Andreas Gampe20c89302014-08-19 17:28:06 -0700676 if (env->ExceptionCheck()) {
Calin Juravleb077e152016-02-18 18:47:37 +0000677 return -1;
Andreas Gampe20c89302014-08-19 17:28:06 -0700678 }
Narayan Kamath11d9f062014-04-23 20:24:57 +0100679
Andreas Gampec38be812016-03-23 15:03:46 -0700680 ScopedUtfChars target_compiler_filter(env, javaTargetCompilerFilter);
681 if (env->ExceptionCheck()) {
682 return -1;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000683 }
Andreas Gampec38be812016-03-23 15:03:46 -0700684
Calin Juravle20c46442017-09-12 00:54:26 -0700685 NullableScopedUtfChars class_loader_context(env, javaClassLoaderContext);
686 if (env->ExceptionCheck()) {
687 return -1;
688 }
689
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700690 return GetDexOptNeeded(env,
691 filename.c_str(),
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700692 instruction_set.c_str(),
Andreas Gampec38be812016-03-23 15:03:46 -0700693 target_compiler_filter.c_str(),
Calin Juravle20c46442017-09-12 00:54:26 -0700694 class_loader_context.c_str(),
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700695 newProfile == JNI_TRUE,
696 downgrade == JNI_TRUE);
Narayan Kamath11d9f062014-04-23 20:24:57 +0100697}
698
Calin Juravleb077e152016-02-18 18:47:37 +0000699// public API
Narayan Kamath11d9f062014-04-23 20:24:57 +0100700static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) {
Richard Uhler06e3f4f2016-05-24 15:42:37 -0700701 ScopedUtfChars filename_utf(env, javaFilename);
702 if (env->ExceptionCheck()) {
703 return JNI_FALSE;
704 }
705
706 const char* filename = filename_utf.c_str();
707 if ((filename == nullptr) || !OS::FileExists(filename)) {
708 LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename << "' does not exist";
709 ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
710 const char* message = (filename == nullptr) ? "<empty file name>" : filename;
711 env->ThrowNew(fnfe.get(), message);
712 return JNI_FALSE;
713 }
714
Richard Uhlerd1472a22016-04-15 15:18:56 -0700715 OatFileAssistant oat_file_assistant(filename, kRuntimeISA, false);
Richard Uhler06e3f4f2016-05-24 15:42:37 -0700716 return oat_file_assistant.IsUpToDate() ? JNI_FALSE : JNI_TRUE;
Dave Allison39c3bfb2014-01-28 18:33:52 -0800717}
718
Andreas Gampec38be812016-03-23 15:03:46 -0700719static jboolean DexFile_isValidCompilerFilter(JNIEnv* env,
720 jclass javeDexFileClass ATTRIBUTE_UNUSED,
721 jstring javaCompilerFilter) {
722 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
723 if (env->ExceptionCheck()) {
724 return -1;
725 }
726
727 CompilerFilter::Filter filter;
728 return CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)
729 ? JNI_TRUE : JNI_FALSE;
730}
731
732static jboolean DexFile_isProfileGuidedCompilerFilter(JNIEnv* env,
733 jclass javeDexFileClass ATTRIBUTE_UNUSED,
734 jstring javaCompilerFilter) {
735 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
736 if (env->ExceptionCheck()) {
737 return -1;
738 }
739
740 CompilerFilter::Filter filter;
741 if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
742 return JNI_FALSE;
743 }
744 return CompilerFilter::DependsOnProfile(filter) ? JNI_TRUE : JNI_FALSE;
745}
746
Andreas Gampe86a785d2016-03-30 17:19:48 -0700747static jstring DexFile_getNonProfileGuidedCompilerFilter(JNIEnv* env,
748 jclass javeDexFileClass ATTRIBUTE_UNUSED,
749 jstring javaCompilerFilter) {
750 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
751 if (env->ExceptionCheck()) {
752 return nullptr;
753 }
754
755 CompilerFilter::Filter filter;
756 if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
757 return javaCompilerFilter;
758 }
759
760 CompilerFilter::Filter new_filter = CompilerFilter::GetNonProfileDependentFilterFrom(filter);
761
762 // Filter stayed the same, return input.
763 if (filter == new_filter) {
764 return javaCompilerFilter;
765 }
766
767 // Create a new string object and return.
768 std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter);
769 return env->NewStringUTF(new_filter_str.c_str());
770}
771
Nicolas Geoffray741d4262017-05-03 13:08:36 +0100772static jstring DexFile_getSafeModeCompilerFilter(JNIEnv* env,
773 jclass javeDexFileClass ATTRIBUTE_UNUSED,
774 jstring javaCompilerFilter) {
775 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
776 if (env->ExceptionCheck()) {
777 return nullptr;
778 }
779
780 CompilerFilter::Filter filter;
781 if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
782 return javaCompilerFilter;
783 }
784
785 CompilerFilter::Filter new_filter = CompilerFilter::GetSafeModeFilterFrom(filter);
786
787 // Filter stayed the same, return input.
788 if (filter == new_filter) {
789 return javaCompilerFilter;
790 }
791
792 // Create a new string object and return.
793 std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter);
794 return env->NewStringUTF(new_filter_str.c_str());
795}
796
Jeff Hao90671be2016-04-22 14:00:06 -0700797static jboolean DexFile_isBackedByOatFile(JNIEnv* env, jclass, jobject cookie) {
798 const OatFile* oat_file = nullptr;
799 std::vector<const DexFile*> dex_files;
800 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
801 DCHECK(env->ExceptionCheck());
802 return false;
803 }
804 return oat_file != nullptr;
805}
806
Calin Juravle367b9d82017-05-15 18:18:39 -0700807static jobjectArray DexFile_getDexFileOutputPaths(JNIEnv* env,
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700808 jclass,
809 jstring javaFilename,
810 jstring javaInstructionSet) {
811 ScopedUtfChars filename(env, javaFilename);
812 if (env->ExceptionCheck()) {
813 return nullptr;
814 }
815
816 ScopedUtfChars instruction_set(env, javaInstructionSet);
817 if (env->ExceptionCheck()) {
818 return nullptr;
819 }
820
821 const InstructionSet target_instruction_set = GetInstructionSetFromString(
822 instruction_set.c_str());
Vladimir Marko33bff252017-11-01 14:35:42 +0000823 if (target_instruction_set == InstructionSet::kNone) {
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700824 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
825 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
826 env->ThrowNew(iae.get(), message.c_str());
827 return nullptr;
828 }
829
830 OatFileAssistant oat_file_assistant(filename.c_str(),
831 target_instruction_set,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700832 /* load_executable= */ false);
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700833
834 std::unique_ptr<OatFile> best_oat_file = oat_file_assistant.GetBestOatFile();
835 if (best_oat_file == nullptr) {
836 return nullptr;
837 }
838
Calin Juravle367b9d82017-05-15 18:18:39 -0700839 std::string oat_filename = best_oat_file->GetLocation();
840 std::string vdex_filename = GetVdexFilename(best_oat_file->GetLocation());
841
842 ScopedLocalRef<jstring> jvdexFilename(env, env->NewStringUTF(vdex_filename.c_str()));
843 if (jvdexFilename.get() == nullptr) {
844 return nullptr;
845 }
846 ScopedLocalRef<jstring> joatFilename(env, env->NewStringUTF(oat_filename.c_str()));
847 if (joatFilename.get() == nullptr) {
848 return nullptr;
849 }
850
851 // Now create output array and copy the set into it.
852 jobjectArray result = env->NewObjectArray(2,
853 WellKnownClasses::java_lang_String,
854 nullptr);
855 env->SetObjectArrayElement(result, 0, jvdexFilename.get());
856 env->SetObjectArrayElement(result, 1, joatFilename.get());
857
858 return result;
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700859}
860
Richard Uhler24ed94f2017-11-16 11:54:29 +0000861static jlong DexFile_getStaticSizeOfDexFile(JNIEnv* env, jclass, jobject cookie) {
862 const OatFile* oat_file = nullptr;
863 std::vector<const DexFile*> dex_files;
864 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
865 DCHECK(env->ExceptionCheck());
866 return 0;
867 }
868
869 uint64_t file_size = 0;
870 for (auto& dex_file : dex_files) {
871 if (dex_file) {
872 file_size += dex_file->GetHeader().file_size_;
873 }
874 }
875 return static_cast<jlong>(file_size);
876}
877
Nicolas Geoffray35a4f482018-05-09 14:49:54 +0100878static void DexFile_setTrusted(JNIEnv* env, jclass, jobject j_cookie) {
879 Runtime* runtime = Runtime::Current();
880 ScopedObjectAccess soa(env);
881
882 // Currently only allow this for debuggable apps.
883 if (!runtime->IsJavaDebuggable()) {
884 ThrowSecurityException("Can't exempt class, process is not debuggable.");
885 return;
886 }
887
888 std::vector<const DexFile*> dex_files;
889 const OatFile* oat_file;
890 if (!ConvertJavaArrayToDexFiles(env, j_cookie, dex_files, oat_file)) {
891 Thread::Current()->AssertPendingException();
892 return;
893 }
894
David Brazdile7681822018-12-14 16:25:33 +0000895 // Assign core platform domain as the dex files are allowed to access all the other domains.
Nicolas Geoffray35a4f482018-05-09 14:49:54 +0100896 for (const DexFile* dex_file : dex_files) {
David Brazdile7681822018-12-14 16:25:33 +0000897 const_cast<DexFile*>(dex_file)->SetHiddenapiDomain(hiddenapi::Domain::kCorePlatform);
Nicolas Geoffray35a4f482018-05-09 14:49:54 +0100898 }
899}
900
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700901static JNINativeMethod gMethods[] = {
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700902 NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)Z"),
Mathieu Chartier00310e02015-10-17 12:46:42 -0700903 NATIVE_METHOD(DexFile,
904 defineClassNative,
905 "(Ljava/lang/String;"
906 "Ljava/lang/ClassLoader;"
907 "Ljava/lang/Object;"
908 "Ldalvik/system/DexFile;"
909 ")Ljava/lang/Class;"),
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800910 NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"),
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700911 NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700912 NATIVE_METHOD(DexFile, getDexOptNeeded,
Calin Juravle20c46442017-09-12 00:54:26 -0700913 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)I"),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700914 NATIVE_METHOD(DexFile, openDexFileNative,
Mathieu Chartier689a7002015-11-20 10:29:42 -0800915 "(Ljava/lang/String;"
916 "Ljava/lang/String;"
917 "I"
918 "Ljava/lang/ClassLoader;"
919 "[Ldalvik/system/DexPathList$Element;"
920 ")Ljava/lang/Object;"),
David Brazdil74582912019-03-01 11:18:19 +0000921 NATIVE_METHOD(DexFile, openInMemoryDexFilesNative,
922 "([Ljava/nio/ByteBuffer;"
923 "[[B"
924 "[I"
925 "[I"
David Brazdil7126c5b2019-03-05 00:02:51 +0000926 "Ljava/lang/ClassLoader;"
927 "[Ldalvik/system/DexPathList$Element;"
David Brazdil74582912019-03-01 11:18:19 +0000928 ")Ljava/lang/Object;"),
David Brazdil35a3f6a2019-03-04 15:59:06 +0000929 NATIVE_METHOD(DexFile, getClassLoaderContext,
930 "(Ljava/lang/ClassLoader;"
931 "[Ldalvik/system/DexPathList$Element;"
932 ")Ljava/lang/String;"),
933 NATIVE_METHOD(DexFile, verifyInBackgroundNative,
934 "(Ljava/lang/Object;"
935 "Ljava/lang/ClassLoader;"
936 "Ljava/lang/String;"
937 ")V"),
Andreas Gampec38be812016-03-23 15:03:46 -0700938 NATIVE_METHOD(DexFile, isValidCompilerFilter, "(Ljava/lang/String;)Z"),
939 NATIVE_METHOD(DexFile, isProfileGuidedCompilerFilter, "(Ljava/lang/String;)Z"),
Andreas Gampe86a785d2016-03-30 17:19:48 -0700940 NATIVE_METHOD(DexFile,
941 getNonProfileGuidedCompilerFilter,
942 "(Ljava/lang/String;)Ljava/lang/String;"),
Nicolas Geoffray741d4262017-05-03 13:08:36 +0100943 NATIVE_METHOD(DexFile,
944 getSafeModeCompilerFilter,
945 "(Ljava/lang/String;)Ljava/lang/String;"),
Jeff Hao90671be2016-04-22 14:00:06 -0700946 NATIVE_METHOD(DexFile, isBackedByOatFile, "(Ljava/lang/Object;)Z"),
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100947 NATIVE_METHOD(DexFile, getDexFileStatus,
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700948 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
Calin Juravle367b9d82017-05-15 18:18:39 -0700949 NATIVE_METHOD(DexFile, getDexFileOutputPaths,
Richard Uhler24ed94f2017-11-16 11:54:29 +0000950 "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"),
Calin Juravle5f9a8012018-02-12 20:27:46 -0800951 NATIVE_METHOD(DexFile, getStaticSizeOfDexFile, "(Ljava/lang/Object;)J"),
952 NATIVE_METHOD(DexFile, getDexFileOptimizationStatus,
Nicolas Geoffray35a4f482018-05-09 14:49:54 +0100953 "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"),
954 NATIVE_METHOD(DexFile, setTrusted, "(Ljava/lang/Object;)V")
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700955};
956
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700957void register_dalvik_system_DexFile(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700958 REGISTER_NATIVE_METHODS("dalvik/system/DexFile");
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700959}
960
961} // namespace art