blob: 0f430874cf19567ffef33127999ffade311adb7c [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
David Sehr891a50e2017-10-27 17:01:07 -070023#include "base/file_utils.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080024#include "base/logging.h"
Andreas Gampe833a4852014-05-21 18:46:59 -070025#include "base/stl_util.h"
Brian Carlstromaded5f72011-10-07 17:15:04 -070026#include "class_linker.h"
Calin Juravle20c46442017-09-12 00:54:26 -070027#include <class_loader_context.h>
Ian Rogers62d6c772013-02-27 08:32:07 -080028#include "common_throws.h"
Andreas Gampec38be812016-03-23 15:03:46 -070029#include "compiler_filter.h"
David Sehr013fd802018-01-11 22:55:24 -080030#include "dex/art_dex_file_loader.h"
David Sehr9e734c72018-01-04 17:56:19 -080031#include "dex/dex_file-inl.h"
32#include "dex/dex_file_loader.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070033#include "jni_internal.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034#include "mirror/class_loader.h"
Ian Rogers05f30572013-02-20 12:13:11 -080035#include "mirror/object-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036#include "mirror/string.h"
Andreas Gampe87583b32017-05-25 11:22:18 -070037#include "native_util.h"
Steven Morelande431e272017-07-18 16:53:49 -070038#include "nativehelper/jni_macros.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070039#include "nativehelper/scoped_local_ref.h"
40#include "nativehelper/scoped_utf_chars.h"
Narayan Kamath8943c1d2016-05-02 13:14:48 +010041#include "oat_file.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080042#include "oat_file_assistant.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070043#include "oat_file_manager.h"
Brian Carlstrom1d9f52b2011-10-13 10:50:45 -070044#include "os.h"
Brian Carlstromaded5f72011-10-07 17:15:04 -070045#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070046#include "scoped_thread_state_change-inl.h"
Calin Juravlebb0b53f2014-05-23 17:33:29 +010047#include "utils.h"
Ian Rogersdd157d72014-05-15 14:47:50 -070048#include "well_known_classes.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070049#include "zip_archive.h"
Brian Carlstromf91c8c32011-09-21 17:30:34 -070050
51namespace art {
52
Andreas Gampe46ee31b2016-12-14 10:11:49 -080053using android::base::StringPrintf;
54
Mathieu Chartiere58991b2015-10-13 07:59:34 -070055static bool ConvertJavaArrayToDexFiles(
56 JNIEnv* env,
57 jobject arrayObject,
58 /*out*/ std::vector<const DexFile*>& dex_files,
59 /*out*/ const OatFile*& oat_file) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -080060 jarray array = reinterpret_cast<jarray>(arrayObject);
61
62 jsize array_size = env->GetArrayLength(array);
63 if (env->ExceptionCheck() == JNI_TRUE) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -070064 return false;
Andreas Gampe324b9bb2015-02-23 16:33:22 -080065 }
66
67 // TODO: Optimize. On 32bit we can use an int array.
68 jboolean is_long_data_copied;
69 jlong* long_data = env->GetLongArrayElements(reinterpret_cast<jlongArray>(array),
70 &is_long_data_copied);
71 if (env->ExceptionCheck() == JNI_TRUE) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -070072 return false;
Andreas Gampe324b9bb2015-02-23 16:33:22 -080073 }
74
Mathieu Chartiere58991b2015-10-13 07:59:34 -070075 oat_file = reinterpret_cast<const OatFile*>(static_cast<uintptr_t>(long_data[kOatFileIndex]));
76 dex_files.reserve(array_size - 1);
77 for (jsize i = kDexFileIndexStart; i < array_size; ++i) {
78 dex_files.push_back(reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(long_data[i])));
Andreas Gampe324b9bb2015-02-23 16:33:22 -080079 }
80
81 env->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), long_data, JNI_ABORT);
Mathieu Chartiere58991b2015-10-13 07:59:34 -070082 return env->ExceptionCheck() != JNI_TRUE;
Andreas Gampe324b9bb2015-02-23 16:33:22 -080083}
84
Mathieu Chartiere58991b2015-10-13 07:59:34 -070085static jlongArray ConvertDexFilesToJavaArray(JNIEnv* env,
86 const OatFile* oat_file,
87 std::vector<std::unique_ptr<const DexFile>>& vec) {
88 // Add one for the oat file.
Mathieu Chartier80b37b72015-10-12 18:13:39 -070089 jlongArray long_array = env->NewLongArray(static_cast<jsize>(kDexFileIndexStart + vec.size()));
Andreas Gampe324b9bb2015-02-23 16:33:22 -080090 if (env->ExceptionCheck() == JNI_TRUE) {
91 return nullptr;
92 }
93
94 jboolean is_long_data_copied;
95 jlong* long_data = env->GetLongArrayElements(long_array, &is_long_data_copied);
96 if (env->ExceptionCheck() == JNI_TRUE) {
97 return nullptr;
98 }
99
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700100 long_data[kOatFileIndex] = reinterpret_cast<uintptr_t>(oat_file);
101 for (size_t i = 0; i < vec.size(); ++i) {
102 long_data[kDexFileIndexStart + i] = reinterpret_cast<uintptr_t>(vec[i].get());
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800103 }
104
105 env->ReleaseLongArrayElements(long_array, long_data, 0);
106 if (env->ExceptionCheck() == JNI_TRUE) {
107 return nullptr;
108 }
109
110 // Now release all the unique_ptrs.
111 for (auto& dex_file : vec) {
112 dex_file.release();
113 }
114
115 return long_array;
116}
117
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700118// A smart pointer that provides read-only access to a Java string's UTF chars.
119// Unlike libcore's NullableScopedUtfChars, this will *not* throw NullPointerException if
120// passed a null jstring. The correct idiom is:
121//
122// NullableScopedUtfChars name(env, javaName);
Brian Carlstromc252c3e2011-10-16 23:21:02 -0700123// if (env->ExceptionCheck()) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700124// return null;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700125// }
126// // ... use name.c_str()
127//
128// TODO: rewrite to get rid of this, or change ScopedUtfChars to offer this option.
129class NullableScopedUtfChars {
Elliott Hughesba8eee12012-01-24 20:25:24 -0800130 public:
131 NullableScopedUtfChars(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700132 mUtfChars = (s != nullptr) ? env->GetStringUTFChars(s, nullptr) : nullptr;
Elliott Hughesba8eee12012-01-24 20:25:24 -0800133 }
134
135 ~NullableScopedUtfChars() {
136 if (mUtfChars) {
137 mEnv->ReleaseStringUTFChars(mString, mUtfChars);
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700138 }
Elliott Hughesba8eee12012-01-24 20:25:24 -0800139 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700140
Elliott Hughesba8eee12012-01-24 20:25:24 -0800141 const char* c_str() const {
142 return mUtfChars;
143 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700144
Elliott Hughesba8eee12012-01-24 20:25:24 -0800145 size_t size() const {
146 return strlen(mUtfChars);
147 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700148
Elliott Hughesba8eee12012-01-24 20:25:24 -0800149 // Element access.
150 const char& operator[](size_t n) const {
151 return mUtfChars[n];
152 }
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700153
Elliott Hughesba8eee12012-01-24 20:25:24 -0800154 private:
155 JNIEnv* mEnv;
156 jstring mString;
157 const char* mUtfChars;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700158
Elliott Hughesba8eee12012-01-24 20:25:24 -0800159 // Disallow copy and assignment.
160 NullableScopedUtfChars(const NullableScopedUtfChars&);
161 void operator=(const NullableScopedUtfChars&);
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700162};
163
Alex Lightea9465e2017-02-16 15:38:35 -0800164static std::unique_ptr<MemMap> AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) {
165 if (end <= start) {
166 ScopedObjectAccess soa(env);
167 ThrowWrappedIOException("Bad range");
168 return nullptr;
169 }
170
171 std::string error_message;
172 size_t length = static_cast<size_t>(end - start);
173 std::unique_ptr<MemMap> dex_mem_map(MemMap::MapAnonymous("DEX data",
174 nullptr,
175 length,
176 PROT_READ | PROT_WRITE,
177 /* low_4gb */ false,
178 /* reuse */ false,
179 &error_message));
180 if (dex_mem_map == nullptr) {
181 ScopedObjectAccess soa(env);
182 ThrowWrappedIOException("%s", error_message.c_str());
183 }
184 return dex_mem_map;
185}
186
187static const DexFile* CreateDexFile(JNIEnv* env, std::unique_ptr<MemMap> dex_mem_map) {
188 std::string location = StringPrintf("Anonymous-DexFile@%p-%p",
189 dex_mem_map->Begin(),
190 dex_mem_map->End());
191 std::string error_message;
David Sehr013fd802018-01-11 22:55:24 -0800192 const ArtDexFileLoader dex_file_loader;
193 std::unique_ptr<const DexFile> dex_file(dex_file_loader.Open(location,
194 0,
195 std::move(dex_mem_map),
196 /* verify */ true,
197 /* verify_location */ true,
198 &error_message));
Alex Lightea9465e2017-02-16 15:38:35 -0800199 if (dex_file == nullptr) {
200 ScopedObjectAccess soa(env);
201 ThrowWrappedIOException("%s", error_message.c_str());
202 return nullptr;
203 }
204
205 if (!dex_file->DisableWrite()) {
206 ScopedObjectAccess soa(env);
207 ThrowWrappedIOException("Failed to make dex file read-only");
208 return nullptr;
209 }
210
211 return dex_file.release();
212}
213
214static jobject CreateSingleDexFileCookie(JNIEnv* env, std::unique_ptr<MemMap> data) {
215 std::unique_ptr<const DexFile> dex_file(CreateDexFile(env, std::move(data)));
216 if (dex_file.get() == nullptr) {
217 DCHECK(env->ExceptionCheck());
218 return nullptr;
219 }
220 std::vector<std::unique_ptr<const DexFile>> dex_files;
221 dex_files.push_back(std::move(dex_file));
222 return ConvertDexFilesToJavaArray(env, nullptr, dex_files);
223}
224
225static jobject DexFile_createCookieWithDirectBuffer(JNIEnv* env,
226 jclass,
227 jobject buffer,
228 jint start,
229 jint end) {
230 uint8_t* base_address = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
231 if (base_address == nullptr) {
232 ScopedObjectAccess soa(env);
233 ThrowWrappedIOException("dexFileBuffer not direct");
234 return 0;
235 }
236
237 std::unique_ptr<MemMap> dex_mem_map(AllocateDexMemoryMap(env, start, end));
238 if (dex_mem_map == nullptr) {
239 DCHECK(Thread::Current()->IsExceptionPending());
240 return 0;
241 }
242
243 size_t length = static_cast<size_t>(end - start);
244 memcpy(dex_mem_map->Begin(), base_address, length);
245 return CreateSingleDexFileCookie(env, std::move(dex_mem_map));
246}
247
248static jobject DexFile_createCookieWithArray(JNIEnv* env,
249 jclass,
250 jbyteArray buffer,
251 jint start,
252 jint end) {
253 std::unique_ptr<MemMap> dex_mem_map(AllocateDexMemoryMap(env, start, end));
254 if (dex_mem_map == nullptr) {
255 DCHECK(Thread::Current()->IsExceptionPending());
256 return 0;
257 }
258
259 auto destination = reinterpret_cast<jbyte*>(dex_mem_map.get()->Begin());
260 env->GetByteArrayRegion(buffer, start, end - start, destination);
261 return CreateSingleDexFileCookie(env, std::move(dex_mem_map));
262}
263
Calin Juravle1f7079b2017-04-18 21:25:37 -0700264// TODO(calin): clean up the unused parameters (here and in libcore).
Mathieu Chartierb190d942015-11-12 10:00:58 -0800265static jobject DexFile_openDexFileNative(JNIEnv* env,
266 jclass,
267 jstring javaSourceName,
Calin Juravle1f7079b2017-04-18 21:25:37 -0700268 jstring javaOutputName ATTRIBUTE_UNUSED,
Mathieu Chartierb190d942015-11-12 10:00:58 -0800269 jint flags ATTRIBUTE_UNUSED,
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800270 jobject class_loader,
271 jobjectArray dex_elements) {
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700272 ScopedUtfChars sourceName(env, javaSourceName);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700273 if (sourceName.c_str() == nullptr) {
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700274 return 0;
275 }
Calin Juravle1f7079b2017-04-18 21:25:37 -0700276
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -0700277 Runtime* const runtime = Runtime::Current();
278 ClassLinker* linker = runtime->GetClassLinker();
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800279 std::vector<std::unique_ptr<const DexFile>> dex_files;
Andreas Gampe833a4852014-05-21 18:46:59 -0700280 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700281 const OatFile* oat_file = nullptr;
Andreas Gampe833a4852014-05-21 18:46:59 -0700282
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -0700283 dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800284 class_loader,
285 dex_elements,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700286 /*out*/ &oat_file,
287 /*out*/ &error_msgs);
Andreas Gampe833a4852014-05-21 18:46:59 -0700288
Richard Uhler66d874d2015-01-15 09:37:19 -0800289 if (!dex_files.empty()) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700290 jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files);
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800291 if (array == nullptr) {
292 ScopedObjectAccess soa(env);
293 for (auto& dex_file : dex_files) {
Vladimir Markocd556b02017-02-03 11:47:34 +0000294 if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800295 dex_file.release();
296 }
297 }
298 }
299 return array;
Brian Carlstrom756ee4e2013-10-03 15:46:12 -0700300 } else {
Vladimir Marko60836d52014-01-16 15:53:38 +0000301 ScopedObjectAccess soa(env);
Andreas Gampe329d1882014-04-08 10:32:19 -0700302 CHECK(!error_msgs.empty());
303 // The most important message is at the end. So set up nesting by going forward, which will
304 // wrap the existing exception as a cause for the following one.
305 auto it = error_msgs.begin();
306 auto itEnd = error_msgs.end();
307 for ( ; it != itEnd; ++it) {
308 ThrowWrappedIOException("%s", it->c_str());
309 }
310
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800311 return nullptr;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700312 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700313}
314
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700315static jboolean DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700316 std::vector<const DexFile*> dex_files;
317 const OatFile* oat_file;
318 if (!ConvertJavaArrayToDexFiles(env, cookie, dex_files, oat_file)) {
319 Thread::Current()->AssertPendingException();
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700320 return JNI_FALSE;
321 }
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700322 Runtime* const runtime = Runtime::Current();
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700323 bool all_deleted = true;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700324 {
325 ScopedObjectAccess soa(env);
Mathieu Chartier0795f232016-09-27 18:43:30 -0700326 ObjPtr<mirror::Object> dex_files_object = soa.Decode<mirror::Object>(cookie);
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700327 ObjPtr<mirror::LongArray> long_dex_files = dex_files_object->AsLongArray();
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700328 // Delete dex files associated with this dalvik.system.DexFile since there should not be running
329 // code using it. dex_files is a vector due to multidex.
330 ClassLinker* const class_linker = runtime->GetClassLinker();
331 int32_t i = kDexFileIndexStart; // Oat file is at index 0.
332 for (const DexFile* dex_file : dex_files) {
333 if (dex_file != nullptr) {
334 // Only delete the dex file if the dex cache is not found to prevent runtime crashes if there
335 // are calls to DexFile.close while the ART DexFile is still in use.
Vladimir Markocd556b02017-02-03 11:47:34 +0000336 if (!class_linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700337 // Clear the element in the array so that we can call close again.
338 long_dex_files->Set(i, 0);
339 delete dex_file;
340 } else {
341 all_deleted = false;
342 }
343 }
344 ++i;
Andreas Gampe833a4852014-05-21 18:46:59 -0700345 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700346 }
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700347
Mathieu Chartierfdccbd42015-10-14 10:58:41 -0700348 // oat_file can be null if we are running without dex2oat.
349 if (all_deleted && oat_file != nullptr) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700350 // If all of the dex files are no longer in use we can unmap the corresponding oat file.
351 VLOG(class_linker) << "Unregistering " << oat_file;
352 runtime->GetOatFileManager().UnRegisterAndDeleteOatFile(oat_file);
353 }
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700354 return all_deleted ? JNI_TRUE : JNI_FALSE;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700355}
356
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700357static jclass DexFile_defineClassNative(JNIEnv* env,
358 jclass,
359 jstring javaName,
360 jobject javaLoader,
Mathieu Chartier00310e02015-10-17 12:46:42 -0700361 jobject cookie,
362 jobject dexFile) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700363 std::vector<const DexFile*> dex_files;
364 const OatFile* oat_file;
365 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out*/ dex_files, /*out*/ oat_file)) {
Brian Carlstrom7571e8b2013-08-12 17:04:14 -0700366 VLOG(class_linker) << "Failed to find dex_file";
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800367 DCHECK(env->ExceptionCheck());
368 return nullptr;
Brian Carlstromaded5f72011-10-07 17:15:04 -0700369 }
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800370
Brian Carlstromdf143242011-10-10 18:05:34 -0700371 ScopedUtfChars class_name(env, javaName);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700372 if (class_name.c_str() == nullptr) {
Brian Carlstrom2e450bf2013-09-06 15:39:46 -0700373 VLOG(class_linker) << "Failed to find class_name";
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700374 return nullptr;
Brian Carlstromdf143242011-10-10 18:05:34 -0700375 }
Elliott Hughes95572412011-12-13 18:14:20 -0800376 const std::string descriptor(DotToDescriptor(class_name.c_str()));
Mathieu Chartiere7c9a8c2014-11-06 16:35:45 -0800377 const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str()));
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700378 for (auto& dex_file : dex_files) {
David Sehr9aa352e2016-09-15 18:13:52 -0700379 const DexFile::ClassDef* dex_class_def =
380 OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash);
Andreas Gampe833a4852014-05-21 18:46:59 -0700381 if (dex_class_def != nullptr) {
382 ScopedObjectAccess soa(env);
383 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Andreas Gampe833a4852014-05-21 18:46:59 -0700384 StackHandleScope<1> hs(soa.Self());
385 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700386 hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
Vladimir Markocd556b02017-02-03 11:47:34 +0000387 ObjPtr<mirror::DexCache> dex_cache =
388 class_linker->RegisterDexFile(*dex_file, class_loader.Get());
389 if (dex_cache == nullptr) {
390 // OOME or InternalError (dexFile already registered with a different class loader).
391 soa.Self()->AssertPendingException();
392 return nullptr;
393 }
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700394 ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(),
395 descriptor.c_str(),
396 hash,
397 class_loader,
398 *dex_file,
399 *dex_class_def);
Mathieu Chartier00310e02015-10-17 12:46:42 -0700400 // Add the used dex file. This only required for the DexFile.loadClass API since normal
401 // class loaders already keep their dex files live.
Mathieu Chartierbc5a7952016-10-17 15:46:31 -0700402 class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile),
Mathieu Chartier00310e02015-10-17 12:46:42 -0700403 class_loader.Get());
Andreas Gampe833a4852014-05-21 18:46:59 -0700404 if (result != nullptr) {
Brian Carlstrom667ab7c2014-10-16 19:12:28 -0700405 VLOG(class_linker) << "DexFile_defineClassNative returning " << result
406 << " for " << class_name.c_str();
Andreas Gampe833a4852014-05-21 18:46:59 -0700407 return soa.AddLocalReference<jclass>(result);
408 }
409 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700410 }
Brian Carlstrom667ab7c2014-10-16 19:12:28 -0700411 VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str();
Andreas Gampe833a4852014-05-21 18:46:59 -0700412 return nullptr;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700413}
414
Andreas Gampe833a4852014-05-21 18:46:59 -0700415// Needed as a compare functor for sets of const char
416struct CharPointerComparator {
417 bool operator()(const char *str1, const char *str2) const {
418 return strcmp(str1, str2) < 0;
419 }
420};
421
422// Note: this can be an expensive call, as we sort out duplicates in MultiDex files.
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800423static jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jobject cookie) {
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700424 const OatFile* oat_file = nullptr;
425 std::vector<const DexFile*> dex_files;
426 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800427 DCHECK(env->ExceptionCheck());
428 return nullptr;
429 }
Andreas Gampe833a4852014-05-21 18:46:59 -0700430
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800431 // Push all class descriptors into a set. Use set instead of unordered_set as we want to
432 // retrieve all in the end.
433 std::set<const char*, CharPointerComparator> descriptors;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700434 for (auto& dex_file : dex_files) {
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800435 for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
436 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
437 const char* descriptor = dex_file->GetClassDescriptor(class_def);
438 descriptors.insert(descriptor);
Andreas Gampe833a4852014-05-21 18:46:59 -0700439 }
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800440 }
Andreas Gampe833a4852014-05-21 18:46:59 -0700441
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800442 // Now create output array and copy the set into it.
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700443 jobjectArray result = env->NewObjectArray(descriptors.size(),
444 WellKnownClasses::java_lang_String,
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800445 nullptr);
446 if (result != nullptr) {
447 auto it = descriptors.begin();
448 auto it_end = descriptors.end();
449 jsize i = 0;
450 for (; it != it_end; it++, ++i) {
451 std::string descriptor(DescriptorToDot(*it));
452 ScopedLocalRef<jstring> jdescriptor(env, env->NewStringUTF(descriptor.c_str()));
453 if (jdescriptor.get() == nullptr) {
454 return nullptr;
Ian Rogersdd157d72014-05-15 14:47:50 -0700455 }
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800456 env->SetObjectArrayElement(result, i, jdescriptor.get());
Ian Rogersdd157d72014-05-15 14:47:50 -0700457 }
Brian Carlstromaded5f72011-10-07 17:15:04 -0700458 }
Ian Rogersdd157d72014-05-15 14:47:50 -0700459 return result;
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700460}
461
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700462static jint GetDexOptNeeded(JNIEnv* env,
463 const char* filename,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700464 const char* instruction_set,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000465 const char* compiler_filter_name,
Calin Juravle20c46442017-09-12 00:54:26 -0700466 const char* class_loader_context,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700467 bool profile_changed,
468 bool downgrade) {
Narayan Kamath11d9f062014-04-23 20:24:57 +0100469 if ((filename == nullptr) || !OS::FileExists(filename)) {
Richard Uhler95abd042015-03-24 09:51:28 -0700470 LOG(ERROR) << "DexFile_getDexOptNeeded file '" << filename << "' does not exist";
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700471 ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
Narayan Kamath11d9f062014-04-23 20:24:57 +0100472 const char* message = (filename == nullptr) ? "<empty file name>" : filename;
Ian Rogers8d31bbd2013-10-13 10:44:14 -0700473 env->ThrowNew(fnfe.get(), message);
Calin Juravleb077e152016-02-18 18:47:37 +0000474 return -1;
Brian Carlstrom1d9f52b2011-10-13 10:50:45 -0700475 }
476
Alex Light6e183f22014-07-18 14:57:04 -0700477 const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set);
Vladimir Marko33bff252017-11-01 14:35:42 +0000478 if (target_instruction_set == InstructionSet::kNone) {
Andreas Gampe20c89302014-08-19 17:28:06 -0700479 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
480 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set));
481 env->ThrowNew(iae.get(), message.c_str());
Calin Juravleb077e152016-02-18 18:47:37 +0000482 return -1;
Andreas Gampe20c89302014-08-19 17:28:06 -0700483 }
Alex Light6e183f22014-07-18 14:57:04 -0700484
Andreas Gampe29d38e72016-03-23 15:31:51 +0000485 CompilerFilter::Filter filter;
486 if (!CompilerFilter::ParseCompilerFilter(compiler_filter_name, &filter)) {
487 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
488 std::string message(StringPrintf("Compiler filter %s is invalid.", compiler_filter_name));
489 env->ThrowNew(iae.get(), message.c_str());
490 return -1;
491 }
492
Calin Juravle20c46442017-09-12 00:54:26 -0700493 std::unique_ptr<ClassLoaderContext> context = nullptr;
494 if (class_loader_context != nullptr) {
495 context = ClassLoaderContext::Create(class_loader_context);
496
497 if (context == nullptr) {
498 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
499 std::string message(StringPrintf("Class loader context '%s' is invalid.",
500 class_loader_context));
501 env->ThrowNew(iae.get(), message.c_str());
502 return -1;
503 }
504 }
505
Richard Uhler66d874d2015-01-15 09:37:19 -0800506 // TODO: Verify the dex location is well formed, and throw an IOException if
507 // not?
Andreas Gampe29d38e72016-03-23 15:31:51 +0000508
Richard Uhlerd1472a22016-04-15 15:18:56 -0700509 OatFileAssistant oat_file_assistant(filename, target_instruction_set, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800510
511 // Always treat elements of the bootclasspath as up-to-date.
512 if (oat_file_assistant.IsInBootClassPath()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700513 return OatFileAssistant::kNoDexOptNeeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800514 }
Calin Juravle44e5efa2017-09-12 00:54:26 -0700515
Calin Juravle20c46442017-09-12 00:54:26 -0700516 return oat_file_assistant.GetDexOptNeeded(filter,
517 profile_changed,
518 downgrade,
519 context.get());
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700520}
521
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100522static jstring DexFile_getDexFileStatus(JNIEnv* env,
523 jclass,
524 jstring javaFilename,
525 jstring javaInstructionSet) {
526 ScopedUtfChars filename(env, javaFilename);
527 if (env->ExceptionCheck()) {
528 return nullptr;
529 }
530
531 ScopedUtfChars instruction_set(env, javaInstructionSet);
532 if (env->ExceptionCheck()) {
533 return nullptr;
534 }
535
536 const InstructionSet target_instruction_set = GetInstructionSetFromString(
537 instruction_set.c_str());
Vladimir Marko33bff252017-11-01 14:35:42 +0000538 if (target_instruction_set == InstructionSet::kNone) {
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100539 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
540 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
541 env->ThrowNew(iae.get(), message.c_str());
542 return nullptr;
543 }
544
545 OatFileAssistant oat_file_assistant(filename.c_str(), target_instruction_set,
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100546 false /* load_executable */);
Richard Uhler46cc64f2016-11-14 14:53:55 +0000547 return env->NewStringUTF(oat_file_assistant.GetStatusDump().c_str());
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100548}
549
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700550static jint DexFile_getDexOptNeeded(JNIEnv* env,
551 jclass,
552 jstring javaFilename,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700553 jstring javaInstructionSet,
Andreas Gampec38be812016-03-23 15:03:46 -0700554 jstring javaTargetCompilerFilter,
Calin Juravle20c46442017-09-12 00:54:26 -0700555 jstring javaClassLoaderContext,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700556 jboolean newProfile,
557 jboolean downgrade) {
Narayan Kamath11d9f062014-04-23 20:24:57 +0100558 ScopedUtfChars filename(env, javaFilename);
Andreas Gampe20c89302014-08-19 17:28:06 -0700559 if (env->ExceptionCheck()) {
Calin Juravleb077e152016-02-18 18:47:37 +0000560 return -1;
Andreas Gampe20c89302014-08-19 17:28:06 -0700561 }
562
Narayan Kamath11d9f062014-04-23 20:24:57 +0100563 ScopedUtfChars instruction_set(env, javaInstructionSet);
Andreas Gampe20c89302014-08-19 17:28:06 -0700564 if (env->ExceptionCheck()) {
Calin Juravleb077e152016-02-18 18:47:37 +0000565 return -1;
Andreas Gampe20c89302014-08-19 17:28:06 -0700566 }
Narayan Kamath11d9f062014-04-23 20:24:57 +0100567
Andreas Gampec38be812016-03-23 15:03:46 -0700568 ScopedUtfChars target_compiler_filter(env, javaTargetCompilerFilter);
569 if (env->ExceptionCheck()) {
570 return -1;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000571 }
Andreas Gampec38be812016-03-23 15:03:46 -0700572
Calin Juravle20c46442017-09-12 00:54:26 -0700573 NullableScopedUtfChars class_loader_context(env, javaClassLoaderContext);
574 if (env->ExceptionCheck()) {
575 return -1;
576 }
577
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700578 return GetDexOptNeeded(env,
579 filename.c_str(),
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700580 instruction_set.c_str(),
Andreas Gampec38be812016-03-23 15:03:46 -0700581 target_compiler_filter.c_str(),
Calin Juravle20c46442017-09-12 00:54:26 -0700582 class_loader_context.c_str(),
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700583 newProfile == JNI_TRUE,
584 downgrade == JNI_TRUE);
Narayan Kamath11d9f062014-04-23 20:24:57 +0100585}
586
Calin Juravleb077e152016-02-18 18:47:37 +0000587// public API
Narayan Kamath11d9f062014-04-23 20:24:57 +0100588static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) {
Richard Uhler06e3f4f2016-05-24 15:42:37 -0700589 ScopedUtfChars filename_utf(env, javaFilename);
590 if (env->ExceptionCheck()) {
591 return JNI_FALSE;
592 }
593
594 const char* filename = filename_utf.c_str();
595 if ((filename == nullptr) || !OS::FileExists(filename)) {
596 LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename << "' does not exist";
597 ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
598 const char* message = (filename == nullptr) ? "<empty file name>" : filename;
599 env->ThrowNew(fnfe.get(), message);
600 return JNI_FALSE;
601 }
602
Richard Uhlerd1472a22016-04-15 15:18:56 -0700603 OatFileAssistant oat_file_assistant(filename, kRuntimeISA, false);
Richard Uhler06e3f4f2016-05-24 15:42:37 -0700604 return oat_file_assistant.IsUpToDate() ? JNI_FALSE : JNI_TRUE;
Dave Allison39c3bfb2014-01-28 18:33:52 -0800605}
606
Andreas Gampec38be812016-03-23 15:03:46 -0700607static jboolean DexFile_isValidCompilerFilter(JNIEnv* env,
608 jclass javeDexFileClass ATTRIBUTE_UNUSED,
609 jstring javaCompilerFilter) {
610 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
611 if (env->ExceptionCheck()) {
612 return -1;
613 }
614
615 CompilerFilter::Filter filter;
616 return CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)
617 ? JNI_TRUE : JNI_FALSE;
618}
619
620static jboolean DexFile_isProfileGuidedCompilerFilter(JNIEnv* env,
621 jclass javeDexFileClass ATTRIBUTE_UNUSED,
622 jstring javaCompilerFilter) {
623 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
624 if (env->ExceptionCheck()) {
625 return -1;
626 }
627
628 CompilerFilter::Filter filter;
629 if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
630 return JNI_FALSE;
631 }
632 return CompilerFilter::DependsOnProfile(filter) ? JNI_TRUE : JNI_FALSE;
633}
634
Andreas Gampe86a785d2016-03-30 17:19:48 -0700635static jstring DexFile_getNonProfileGuidedCompilerFilter(JNIEnv* env,
636 jclass javeDexFileClass ATTRIBUTE_UNUSED,
637 jstring javaCompilerFilter) {
638 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
639 if (env->ExceptionCheck()) {
640 return nullptr;
641 }
642
643 CompilerFilter::Filter filter;
644 if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
645 return javaCompilerFilter;
646 }
647
648 CompilerFilter::Filter new_filter = CompilerFilter::GetNonProfileDependentFilterFrom(filter);
649
650 // Filter stayed the same, return input.
651 if (filter == new_filter) {
652 return javaCompilerFilter;
653 }
654
655 // Create a new string object and return.
656 std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter);
657 return env->NewStringUTF(new_filter_str.c_str());
658}
659
Nicolas Geoffray741d4262017-05-03 13:08:36 +0100660static jstring DexFile_getSafeModeCompilerFilter(JNIEnv* env,
661 jclass javeDexFileClass ATTRIBUTE_UNUSED,
662 jstring javaCompilerFilter) {
663 ScopedUtfChars compiler_filter(env, javaCompilerFilter);
664 if (env->ExceptionCheck()) {
665 return nullptr;
666 }
667
668 CompilerFilter::Filter filter;
669 if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
670 return javaCompilerFilter;
671 }
672
673 CompilerFilter::Filter new_filter = CompilerFilter::GetSafeModeFilterFrom(filter);
674
675 // Filter stayed the same, return input.
676 if (filter == new_filter) {
677 return javaCompilerFilter;
678 }
679
680 // Create a new string object and return.
681 std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter);
682 return env->NewStringUTF(new_filter_str.c_str());
683}
684
Jeff Hao90671be2016-04-22 14:00:06 -0700685static jboolean DexFile_isBackedByOatFile(JNIEnv* env, jclass, jobject cookie) {
686 const OatFile* oat_file = nullptr;
687 std::vector<const DexFile*> dex_files;
688 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
689 DCHECK(env->ExceptionCheck());
690 return false;
691 }
692 return oat_file != nullptr;
693}
694
Calin Juravle367b9d82017-05-15 18:18:39 -0700695static jobjectArray DexFile_getDexFileOutputPaths(JNIEnv* env,
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700696 jclass,
697 jstring javaFilename,
698 jstring javaInstructionSet) {
699 ScopedUtfChars filename(env, javaFilename);
700 if (env->ExceptionCheck()) {
701 return nullptr;
702 }
703
704 ScopedUtfChars instruction_set(env, javaInstructionSet);
705 if (env->ExceptionCheck()) {
706 return nullptr;
707 }
708
709 const InstructionSet target_instruction_set = GetInstructionSetFromString(
710 instruction_set.c_str());
Vladimir Marko33bff252017-11-01 14:35:42 +0000711 if (target_instruction_set == InstructionSet::kNone) {
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700712 ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
713 std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
714 env->ThrowNew(iae.get(), message.c_str());
715 return nullptr;
716 }
717
718 OatFileAssistant oat_file_assistant(filename.c_str(),
719 target_instruction_set,
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700720 false /* load_executable */);
721
722 std::unique_ptr<OatFile> best_oat_file = oat_file_assistant.GetBestOatFile();
723 if (best_oat_file == nullptr) {
724 return nullptr;
725 }
726
Calin Juravle367b9d82017-05-15 18:18:39 -0700727 std::string oat_filename = best_oat_file->GetLocation();
728 std::string vdex_filename = GetVdexFilename(best_oat_file->GetLocation());
729
730 ScopedLocalRef<jstring> jvdexFilename(env, env->NewStringUTF(vdex_filename.c_str()));
731 if (jvdexFilename.get() == nullptr) {
732 return nullptr;
733 }
734 ScopedLocalRef<jstring> joatFilename(env, env->NewStringUTF(oat_filename.c_str()));
735 if (joatFilename.get() == nullptr) {
736 return nullptr;
737 }
738
739 // Now create output array and copy the set into it.
740 jobjectArray result = env->NewObjectArray(2,
741 WellKnownClasses::java_lang_String,
742 nullptr);
743 env->SetObjectArrayElement(result, 0, jvdexFilename.get());
744 env->SetObjectArrayElement(result, 1, joatFilename.get());
745
746 return result;
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700747}
748
Richard Uhler24ed94f2017-11-16 11:54:29 +0000749static jlong DexFile_getStaticSizeOfDexFile(JNIEnv* env, jclass, jobject cookie) {
750 const OatFile* oat_file = nullptr;
751 std::vector<const DexFile*> dex_files;
752 if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
753 DCHECK(env->ExceptionCheck());
754 return 0;
755 }
756
757 uint64_t file_size = 0;
758 for (auto& dex_file : dex_files) {
759 if (dex_file) {
760 file_size += dex_file->GetHeader().file_size_;
761 }
762 }
763 return static_cast<jlong>(file_size);
764}
765
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700766static JNINativeMethod gMethods[] = {
Mathieu Chartier1d7d7f12015-09-25 16:48:57 -0700767 NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)Z"),
Mathieu Chartier00310e02015-10-17 12:46:42 -0700768 NATIVE_METHOD(DexFile,
769 defineClassNative,
770 "(Ljava/lang/String;"
771 "Ljava/lang/ClassLoader;"
772 "Ljava/lang/Object;"
773 "Ldalvik/system/DexFile;"
774 ")Ljava/lang/Class;"),
Andreas Gampe324b9bb2015-02-23 16:33:22 -0800775 NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"),
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700776 NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700777 NATIVE_METHOD(DexFile, getDexOptNeeded,
Calin Juravle20c46442017-09-12 00:54:26 -0700778 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)I"),
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700779 NATIVE_METHOD(DexFile, openDexFileNative,
Mathieu Chartier689a7002015-11-20 10:29:42 -0800780 "(Ljava/lang/String;"
781 "Ljava/lang/String;"
782 "I"
783 "Ljava/lang/ClassLoader;"
784 "[Ldalvik/system/DexPathList$Element;"
785 ")Ljava/lang/Object;"),
Alex Lightea9465e2017-02-16 15:38:35 -0800786 NATIVE_METHOD(DexFile, createCookieWithDirectBuffer,
787 "(Ljava/nio/ByteBuffer;II)Ljava/lang/Object;"),
788 NATIVE_METHOD(DexFile, createCookieWithArray, "([BII)Ljava/lang/Object;"),
Andreas Gampec38be812016-03-23 15:03:46 -0700789 NATIVE_METHOD(DexFile, isValidCompilerFilter, "(Ljava/lang/String;)Z"),
790 NATIVE_METHOD(DexFile, isProfileGuidedCompilerFilter, "(Ljava/lang/String;)Z"),
Andreas Gampe86a785d2016-03-30 17:19:48 -0700791 NATIVE_METHOD(DexFile,
792 getNonProfileGuidedCompilerFilter,
793 "(Ljava/lang/String;)Ljava/lang/String;"),
Nicolas Geoffray741d4262017-05-03 13:08:36 +0100794 NATIVE_METHOD(DexFile,
795 getSafeModeCompilerFilter,
796 "(Ljava/lang/String;)Ljava/lang/String;"),
Jeff Hao90671be2016-04-22 14:00:06 -0700797 NATIVE_METHOD(DexFile, isBackedByOatFile, "(Ljava/lang/Object;)Z"),
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100798 NATIVE_METHOD(DexFile, getDexFileStatus,
Philip Cuadrab55ad7c2016-07-12 16:37:40 -0700799 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
Calin Juravle367b9d82017-05-15 18:18:39 -0700800 NATIVE_METHOD(DexFile, getDexFileOutputPaths,
Richard Uhler24ed94f2017-11-16 11:54:29 +0000801 "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"),
802 NATIVE_METHOD(DexFile, getStaticSizeOfDexFile, "(Ljava/lang/Object;)J")
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700803};
804
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700805void register_dalvik_system_DexFile(JNIEnv* env) {
Elliott Hugheseac76672012-05-24 21:56:51 -0700806 REGISTER_NATIVE_METHODS("dalvik/system/DexFile");
Brian Carlstromf91c8c32011-09-21 17:30:34 -0700807}
808
809} // namespace art