1f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom/* 2f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * Copyright (C) 2008 The Android Open Source Project 3f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * 4f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 5f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * you may not use this file except in compliance with the License. 6f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * You may obtain a copy of the License at 7f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * 8f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 9f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * 10f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * Unless required by applicable law or agreed to in writing, software 11f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 12f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * See the License for the specific language governing permissions and 14f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * limitations under the License. 15f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom */ 16f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "dalvik_system_DexFile.h" 18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 198943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath#include <sstream> 208943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath 2146ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h" 2246ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 2307ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 24833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe#include "base/stl_util.h" 25aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "class_linker.h" 2662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h" 27c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe#include "compiler_filter.h" 284f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 29eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 3105f3057d6a4d23d712092ccd36a531590bff323bIan Rogers#include "mirror/object-inl.h" 322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/string.h" 338943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath#include "oat_file.h" 3466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "oat_file_assistant.h" 35f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier#include "oat_file_manager.h" 361d9f52b7ca91c6d30b7acfac1c9ab24d93fff470Brian Carlstrom#include "os.h" 37aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "runtime.h" 380795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h" 39c981848a3425662034c5429b61c035e7533b896dIan Rogers#include "ScopedLocalRef.h" 40f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom#include "ScopedUtfChars.h" 41bb0b53f58f11c628f077603b56077dfed1a18f11Calin Juravle#include "utils.h" 42dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers#include "well_known_classes.h" 43eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "zip_archive.h" 44f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 45f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromnamespace art { 46f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 4746ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf; 4846ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 49e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic bool ConvertJavaArrayToDexFiles( 50e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier JNIEnv* env, 51e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jobject arrayObject, 52e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier /*out*/ std::vector<const DexFile*>& dex_files, 53e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier /*out*/ const OatFile*& oat_file) { 54324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jarray array = reinterpret_cast<jarray>(arrayObject); 55324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 56324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jsize array_size = env->GetArrayLength(array); 57324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (env->ExceptionCheck() == JNI_TRUE) { 58e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier return false; 59324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 60324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 61324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe // TODO: Optimize. On 32bit we can use an int array. 62324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jboolean is_long_data_copied; 63324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jlong* long_data = env->GetLongArrayElements(reinterpret_cast<jlongArray>(array), 64324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe &is_long_data_copied); 65324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (env->ExceptionCheck() == JNI_TRUE) { 66e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier return false; 67324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 68324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 69e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier oat_file = reinterpret_cast<const OatFile*>(static_cast<uintptr_t>(long_data[kOatFileIndex])); 70e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier dex_files.reserve(array_size - 1); 71e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier for (jsize i = kDexFileIndexStart; i < array_size; ++i) { 72e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier dex_files.push_back(reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(long_data[i]))); 73324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 74324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 75324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe env->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), long_data, JNI_ABORT); 76e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier return env->ExceptionCheck() != JNI_TRUE; 77324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe} 78324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 79e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jlongArray ConvertDexFilesToJavaArray(JNIEnv* env, 80e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const OatFile* oat_file, 81e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier std::vector<std::unique_ptr<const DexFile>>& vec) { 82e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // Add one for the oat file. 8380b37b7e679a530738c9bcbd39873b6dacf177e5Mathieu Chartier jlongArray long_array = env->NewLongArray(static_cast<jsize>(kDexFileIndexStart + vec.size())); 84324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (env->ExceptionCheck() == JNI_TRUE) { 85324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 86324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 87324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 88324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jboolean is_long_data_copied; 89324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jlong* long_data = env->GetLongArrayElements(long_array, &is_long_data_copied); 90324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (env->ExceptionCheck() == JNI_TRUE) { 91324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 92324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 93324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 94e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier long_data[kOatFileIndex] = reinterpret_cast<uintptr_t>(oat_file); 95e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier for (size_t i = 0; i < vec.size(); ++i) { 96e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier long_data[kDexFileIndexStart + i] = reinterpret_cast<uintptr_t>(vec[i].get()); 97324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 98324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 99324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe env->ReleaseLongArrayElements(long_array, long_data, 0); 100324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (env->ExceptionCheck() == JNI_TRUE) { 101324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 102324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 103324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 104324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe // Now release all the unique_ptrs. 105324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe for (auto& dex_file : vec) { 106324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe dex_file.release(); 107324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 108324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 109324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return long_array; 110324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe} 111324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 112f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// A smart pointer that provides read-only access to a Java string's UTF chars. 113f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// Unlike libcore's NullableScopedUtfChars, this will *not* throw NullPointerException if 114f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// passed a null jstring. The correct idiom is: 115f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// 116f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// NullableScopedUtfChars name(env, javaName); 117c252c3eacd83a0c110dd065690a7f652be35b0e7Brian Carlstrom// if (env->ExceptionCheck()) { 1182cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier// return null; 119f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// } 120f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// // ... use name.c_str() 121f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// 122f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// TODO: rewrite to get rid of this, or change ScopedUtfChars to offer this option. 123f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromclass NullableScopedUtfChars { 124ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public: 125ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes NullableScopedUtfChars(JNIEnv* env, jstring s) : mEnv(env), mString(s) { 1262cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier mUtfChars = (s != nullptr) ? env->GetStringUTFChars(s, nullptr) : nullptr; 127ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes } 128f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 129ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes ~NullableScopedUtfChars() { 130ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes if (mUtfChars) { 131ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes mEnv->ReleaseStringUTFChars(mString, mUtfChars); 132f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom } 133ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes } 134f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 135ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes const char* c_str() const { 136ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes return mUtfChars; 137ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes } 138f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 139ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes size_t size() const { 140ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes return strlen(mUtfChars); 141ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes } 142f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 143ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes // Element access. 144ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes const char& operator[](size_t n) const { 145ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes return mUtfChars[n]; 146ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes } 147f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 148ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes private: 149ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes JNIEnv* mEnv; 150ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes jstring mString; 151ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes const char* mUtfChars; 152f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 153ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes // Disallow copy and assignment. 154ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes NullableScopedUtfChars(const NullableScopedUtfChars&); 155ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes void operator=(const NullableScopedUtfChars&); 156f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}; 157f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 158ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic std::unique_ptr<MemMap> AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) { 159ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (end <= start) { 160ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ScopedObjectAccess soa(env); 161ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ThrowWrappedIOException("Bad range"); 162ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return nullptr; 163ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 164ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 165ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::string error_message; 166ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light size_t length = static_cast<size_t>(end - start); 167ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::unique_ptr<MemMap> dex_mem_map(MemMap::MapAnonymous("DEX data", 168ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light nullptr, 169ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light length, 170ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light PROT_READ | PROT_WRITE, 171ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light /* low_4gb */ false, 172ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light /* reuse */ false, 173ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light &error_message)); 174ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (dex_mem_map == nullptr) { 175ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ScopedObjectAccess soa(env); 176ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ThrowWrappedIOException("%s", error_message.c_str()); 177ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 178ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return dex_mem_map; 179ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light} 180ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 181ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic const DexFile* CreateDexFile(JNIEnv* env, std::unique_ptr<MemMap> dex_mem_map) { 182ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::string location = StringPrintf("Anonymous-DexFile@%p-%p", 183ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light dex_mem_map->Begin(), 184ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light dex_mem_map->End()); 185ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::string error_message; 186ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::unique_ptr<const DexFile> dex_file(DexFile::Open(location, 187ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 0, 188ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::move(dex_mem_map), 189ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light /* verify */ true, 190ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light /* verify_location */ true, 191ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light &error_message)); 192ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (dex_file == nullptr) { 193ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ScopedObjectAccess soa(env); 194ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ThrowWrappedIOException("%s", error_message.c_str()); 195ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return nullptr; 196ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 197ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 198ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (!dex_file->DisableWrite()) { 199ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ScopedObjectAccess soa(env); 200ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ThrowWrappedIOException("Failed to make dex file read-only"); 201ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return nullptr; 202ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 203ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 204ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return dex_file.release(); 205ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light} 206ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 207ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic jobject CreateSingleDexFileCookie(JNIEnv* env, std::unique_ptr<MemMap> data) { 208ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::unique_ptr<const DexFile> dex_file(CreateDexFile(env, std::move(data))); 209ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (dex_file.get() == nullptr) { 210ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light DCHECK(env->ExceptionCheck()); 211ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return nullptr; 212ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 213ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::vector<std::unique_ptr<const DexFile>> dex_files; 214ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light dex_files.push_back(std::move(dex_file)); 215ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return ConvertDexFilesToJavaArray(env, nullptr, dex_files); 216ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light} 217ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 218ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic jobject DexFile_createCookieWithDirectBuffer(JNIEnv* env, 219ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jclass, 220ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jobject buffer, 221ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jint start, 222ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jint end) { 223ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light uint8_t* base_address = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buffer)); 224ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (base_address == nullptr) { 225ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ScopedObjectAccess soa(env); 226ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light ThrowWrappedIOException("dexFileBuffer not direct"); 227ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return 0; 228ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 229ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 230ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::unique_ptr<MemMap> dex_mem_map(AllocateDexMemoryMap(env, start, end)); 231ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (dex_mem_map == nullptr) { 232ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light DCHECK(Thread::Current()->IsExceptionPending()); 233ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return 0; 234ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 235ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 236ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light size_t length = static_cast<size_t>(end - start); 237ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light memcpy(dex_mem_map->Begin(), base_address, length); 238ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return CreateSingleDexFileCookie(env, std::move(dex_mem_map)); 239ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light} 240ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 241ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic jobject DexFile_createCookieWithArray(JNIEnv* env, 242ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jclass, 243ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jbyteArray buffer, 244ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jint start, 245ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light jint end) { 246ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light std::unique_ptr<MemMap> dex_mem_map(AllocateDexMemoryMap(env, start, end)); 247ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light if (dex_mem_map == nullptr) { 248ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light DCHECK(Thread::Current()->IsExceptionPending()); 249ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return 0; 250ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light } 251ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 252ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light auto destination = reinterpret_cast<jbyte*>(dex_mem_map.get()->Begin()); 253ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light env->GetByteArrayRegion(buffer, start, end - start, destination); 254ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light return CreateSingleDexFileCookie(env, std::move(dex_mem_map)); 255ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light} 256ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light 257c23f851300109b1c8fd4b3f0b70cb5105ef1aa7fCalin Juravle// TODO(calin): clean up the unused parameters (here and in libcore). 258b190d945459253c329062dab2440671828275767Mathieu Chartierstatic jobject DexFile_openDexFileNative(JNIEnv* env, 259b190d945459253c329062dab2440671828275767Mathieu Chartier jclass, 260b190d945459253c329062dab2440671828275767Mathieu Chartier jstring javaSourceName, 261c23f851300109b1c8fd4b3f0b70cb5105ef1aa7fCalin Juravle jstring javaOutputName ATTRIBUTE_UNUSED, 262b190d945459253c329062dab2440671828275767Mathieu Chartier jint flags ATTRIBUTE_UNUSED, 263fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier jobject class_loader, 264fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier jobjectArray dex_elements) { 265f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom ScopedUtfChars sourceName(env, javaSourceName); 2662cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (sourceName.c_str() == nullptr) { 267f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom return 0; 268f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom } 269c23f851300109b1c8fd4b3f0b70cb5105ef1aa7fCalin Juravle 270f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier Runtime* const runtime = Runtime::Current(); 271f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier ClassLinker* linker = runtime->GetClassLinker(); 272324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe std::vector<std::unique_ptr<const DexFile>> dex_files; 273329d18806792771dfee064203fe27875d79cd53aAndreas Gampe std::vector<std::string> error_msgs; 274e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const OatFile* oat_file = nullptr; 275756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom 276f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(), 277fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier class_loader, 278fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier dex_elements, 279e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier /*out*/ &oat_file, 280e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier /*out*/ &error_msgs); 281833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe 28266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler if (!dex_files.empty()) { 283e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files); 284324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (array == nullptr) { 285324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe ScopedObjectAccess soa(env); 286324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe for (auto& dex_file : dex_files) { 287cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) { 288324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe dex_file.release(); 289324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 290324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 291324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 292324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return array; 293262bf46ddc91e5b4fbd367127ff21a1877d939f2jeffhao } else { 29460836d5a9bcf8b30984aae4279a4f6233b0bf622Vladimir Marko ScopedObjectAccess soa(env); 295329d18806792771dfee064203fe27875d79cd53aAndreas Gampe CHECK(!error_msgs.empty()); 296329d18806792771dfee064203fe27875d79cd53aAndreas Gampe // The most important message is at the end. So set up nesting by going forward, which will 297329d18806792771dfee064203fe27875d79cd53aAndreas Gampe // wrap the existing exception as a cause for the following one. 298329d18806792771dfee064203fe27875d79cd53aAndreas Gampe auto it = error_msgs.begin(); 299329d18806792771dfee064203fe27875d79cd53aAndreas Gampe auto itEnd = error_msgs.end(); 300329d18806792771dfee064203fe27875d79cd53aAndreas Gampe for ( ; it != itEnd; ++it) { 301329d18806792771dfee064203fe27875d79cd53aAndreas Gampe ThrowWrappedIOException("%s", it->c_str()); 302329d18806792771dfee064203fe27875d79cd53aAndreas Gampe } 303329d18806792771dfee064203fe27875d79cd53aAndreas Gampe 304324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 305aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 306aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom} 307aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 3081d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartierstatic jboolean DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) { 309e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier std::vector<const DexFile*> dex_files; 310e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const OatFile* oat_file; 311e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier if (!ConvertJavaArrayToDexFiles(env, cookie, dex_files, oat_file)) { 312e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier Thread::Current()->AssertPendingException(); 3131d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier return JNI_FALSE; 3141d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier } 315e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier Runtime* const runtime = Runtime::Current(); 3161d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier bool all_deleted = true; 317e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier { 318e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier ScopedObjectAccess soa(env); 3190795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::Object> dex_files_object = soa.Decode<mirror::Object>(cookie); 320bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier ObjPtr<mirror::LongArray> long_dex_files = dex_files_object->AsLongArray(); 321e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // Delete dex files associated with this dalvik.system.DexFile since there should not be running 322e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // code using it. dex_files is a vector due to multidex. 323e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier ClassLinker* const class_linker = runtime->GetClassLinker(); 324e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier int32_t i = kDexFileIndexStart; // Oat file is at index 0. 325e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier for (const DexFile* dex_file : dex_files) { 326e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier if (dex_file != nullptr) { 327e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // Only delete the dex file if the dex cache is not found to prevent runtime crashes if there 328e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // are calls to DexFile.close while the ART DexFile is still in use. 329cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko if (!class_linker->IsDexFileRegistered(soa.Self(), *dex_file)) { 330e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // Clear the element in the array so that we can call close again. 331e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier long_dex_files->Set(i, 0); 332e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier delete dex_file; 333e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } else { 334e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier all_deleted = false; 335e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 336e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 337e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier ++i; 338833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe } 339aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 3401d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier 341fdccbd418694a4216151e562faa5fd9fe6e12057Mathieu Chartier // oat_file can be null if we are running without dex2oat. 342fdccbd418694a4216151e562faa5fd9fe6e12057Mathieu Chartier if (all_deleted && oat_file != nullptr) { 343e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier // If all of the dex files are no longer in use we can unmap the corresponding oat file. 344e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier VLOG(class_linker) << "Unregistering " << oat_file; 345e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier runtime->GetOatFileManager().UnRegisterAndDeleteOatFile(oat_file); 346e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier } 3471d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier return all_deleted ? JNI_TRUE : JNI_FALSE; 348f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom} 349f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 350e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jclass DexFile_defineClassNative(JNIEnv* env, 351e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jclass, 352e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jstring javaName, 353e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jobject javaLoader, 35400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier jobject cookie, 35500310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier jobject dexFile) { 356e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier std::vector<const DexFile*> dex_files; 357e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const OatFile* oat_file; 358e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier if (!ConvertJavaArrayToDexFiles(env, cookie, /*out*/ dex_files, /*out*/ oat_file)) { 3597571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom VLOG(class_linker) << "Failed to find dex_file"; 360324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe DCHECK(env->ExceptionCheck()); 361324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 362aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 363324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 364df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom ScopedUtfChars class_name(env, javaName); 3652cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (class_name.c_str() == nullptr) { 3662e450bf45e1bacc9c356f6ab239ccfb31bd8d7e4Brian Carlstrom VLOG(class_linker) << "Failed to find class_name"; 3672cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return nullptr; 368df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom } 369955724179c6c739524f610023287f56b24dc31deElliott Hughes const std::string descriptor(DotToDescriptor(class_name.c_str())); 370e7c9a8c2b8481aafbc6af4ce6229bd361ba24742Mathieu Chartier const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str())); 371e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier for (auto& dex_file : dex_files) { 3729aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr const DexFile::ClassDef* dex_class_def = 3739aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash); 374833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe if (dex_class_def != nullptr) { 375833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe ScopedObjectAccess soa(env); 376833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 377833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe StackHandleScope<1> hs(soa.Self()); 378833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe Handle<mirror::ClassLoader> class_loader( 3790795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader))); 380cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko ObjPtr<mirror::DexCache> dex_cache = 381cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko class_linker->RegisterDexFile(*dex_file, class_loader.Get()); 382cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko if (dex_cache == nullptr) { 383cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko // OOME or InternalError (dexFile already registered with a different class loader). 384cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko soa.Self()->AssertPendingException(); 385cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko return nullptr; 386cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko } 387bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(), 388bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier descriptor.c_str(), 389bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier hash, 390bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier class_loader, 391bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier *dex_file, 392bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier *dex_class_def); 39300310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier // Add the used dex file. This only required for the DexFile.loadClass API since normal 39400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier // class loaders already keep their dex files live. 395bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile), 39600310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier class_loader.Get()); 397833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe if (result != nullptr) { 398667ab7c174ebdb16fc18487901c6857709adcdb8Brian Carlstrom VLOG(class_linker) << "DexFile_defineClassNative returning " << result 399667ab7c174ebdb16fc18487901c6857709adcdb8Brian Carlstrom << " for " << class_name.c_str(); 400833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe return soa.AddLocalReference<jclass>(result); 401833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe } 402833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe } 403aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 404667ab7c174ebdb16fc18487901c6857709adcdb8Brian Carlstrom VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str(); 405833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe return nullptr; 406f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom} 407f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 408833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe// Needed as a compare functor for sets of const char 409833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampestruct CharPointerComparator { 410833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe bool operator()(const char *str1, const char *str2) const { 411833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe return strcmp(str1, str2) < 0; 412833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe } 413833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe}; 414833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe 415833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe// Note: this can be an expensive call, as we sort out duplicates in MultiDex files. 416324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampestatic jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jobject cookie) { 417e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const OatFile* oat_file = nullptr; 418e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier std::vector<const DexFile*> dex_files; 419e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) { 420324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe DCHECK(env->ExceptionCheck()); 421324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 422324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 423324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe 424324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe // Push all class descriptors into a set. Use set instead of unordered_set as we want to 425324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe // retrieve all in the end. 426324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe std::set<const char*, CharPointerComparator> descriptors; 427e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier for (auto& dex_file : dex_files) { 428324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) { 429324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); 430324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe const char* descriptor = dex_file->GetClassDescriptor(class_def); 431324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe descriptors.insert(descriptor); 432833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe } 433324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe } 434833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe 435324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe // Now create output array and copy the set into it. 436e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jobjectArray result = env->NewObjectArray(descriptors.size(), 437e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier WellKnownClasses::java_lang_String, 438324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe nullptr); 439324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (result != nullptr) { 440324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe auto it = descriptors.begin(); 441324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe auto it_end = descriptors.end(); 442324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe jsize i = 0; 443324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe for (; it != it_end; it++, ++i) { 444324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe std::string descriptor(DescriptorToDot(*it)); 445324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe ScopedLocalRef<jstring> jdescriptor(env, env->NewStringUTF(descriptor.c_str())); 446324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe if (jdescriptor.get() == nullptr) { 447324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe return nullptr; 448dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers } 449324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe env->SetObjectArrayElement(result, i, jdescriptor.get()); 450dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers } 45103a20ba67cfdc46f5ad8d77242a666a4cb0512f2Brian Carlstrom } 452dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers return result; 453f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom} 454f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 455e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jint GetDexOptNeeded(JNIEnv* env, 456e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const char* filename, 457e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier const char* instruction_set, 45829d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe const char* compiler_filter_name, 45929d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe bool profile_changed) { 46011d9f06a96a6909905c248ed684366190140095cNarayan Kamath if ((filename == nullptr) || !OS::FileExists(filename)) { 46195abd04d211470ea4b9b9191b96dd0f32e7ce3a4Richard Uhler LOG(ERROR) << "DexFile_getDexOptNeeded file '" << filename << "' does not exist"; 4628d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException")); 46311d9f06a96a6909905c248ed684366190140095cNarayan Kamath const char* message = (filename == nullptr) ? "<empty file name>" : filename; 4648d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers env->ThrowNew(fnfe.get(), message); 465b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle return -1; 4661d9f52b7ca91c6d30b7acfac1c9ab24d93fff470Brian Carlstrom } 4671d9f52b7ca91c6d30b7acfac1c9ab24d93fff470Brian Carlstrom 4686e183f2e973a20f2eaca135c240908e1bf98c5d0Alex Light const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set); 46920c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe if (target_instruction_set == kNone) { 47020c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); 47120c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set)); 47220c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe env->ThrowNew(iae.get(), message.c_str()); 473b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle return -1; 47420c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe } 4756e183f2e973a20f2eaca135c240908e1bf98c5d0Alex Light 47629d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe CompilerFilter::Filter filter; 47729d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe if (!CompilerFilter::ParseCompilerFilter(compiler_filter_name, &filter)) { 47829d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); 47929d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe std::string message(StringPrintf("Compiler filter %s is invalid.", compiler_filter_name)); 48029d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe env->ThrowNew(iae.get(), message.c_str()); 48129d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe return -1; 48229d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe } 48329d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe 48466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler // TODO: Verify the dex location is well formed, and throw an IOException if 48566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler // not? 48629d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe 487d1472a27e856ec68ab5a27abaaebe9c61d91d343Richard Uhler OatFileAssistant oat_file_assistant(filename, target_instruction_set, false); 4886e183f2e973a20f2eaca135c240908e1bf98c5d0Alex Light 48966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler // Always treat elements of the bootclasspath as up-to-date. 49066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler if (oat_file_assistant.IsInBootClassPath()) { 49195abd04d211470ea4b9b9191b96dd0f32e7ce3a4Richard Uhler return OatFileAssistant::kNoDexOptNeeded; 49246774767fcf7780d1455e755729198648d08742eIgor Murashkin } 493d1472a27e856ec68ab5a27abaaebe9c61d91d343Richard Uhler return oat_file_assistant.GetDexOptNeeded(filter, profile_changed); 494f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom} 495f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 4968943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamathstatic jstring DexFile_getDexFileStatus(JNIEnv* env, 4978943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath jclass, 4988943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath jstring javaFilename, 4998943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath jstring javaInstructionSet) { 5008943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath ScopedUtfChars filename(env, javaFilename); 5018943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath if (env->ExceptionCheck()) { 5028943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath return nullptr; 5038943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath } 5048943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath 5058943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath ScopedUtfChars instruction_set(env, javaInstructionSet); 5068943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath if (env->ExceptionCheck()) { 5078943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath return nullptr; 5088943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath } 5098943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath 5108943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath const InstructionSet target_instruction_set = GetInstructionSetFromString( 5118943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath instruction_set.c_str()); 5128943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath if (target_instruction_set == kNone) { 5138943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); 5148943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str())); 5158943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath env->ThrowNew(iae.get(), message.c_str()); 5168943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath return nullptr; 5178943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath } 5188943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath 5198943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath OatFileAssistant oat_file_assistant(filename.c_str(), target_instruction_set, 5208943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath false /* load_executable */); 52146cc64f11b1b1f0ac5e4aebd665b325a68d4d42fRichard Uhler return env->NewStringUTF(oat_file_assistant.GetStatusDump().c_str()); 5228943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath} 5238943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath 524e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jint DexFile_getDexOptNeeded(JNIEnv* env, 525e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jclass, 526e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jstring javaFilename, 527e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier jstring javaInstructionSet, 528c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe jstring javaTargetCompilerFilter, 529c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe jboolean newProfile) { 53011d9f06a96a6909905c248ed684366190140095cNarayan Kamath ScopedUtfChars filename(env, javaFilename); 53120c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe if (env->ExceptionCheck()) { 532b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle return -1; 53320c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe } 53420c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe 53511d9f06a96a6909905c248ed684366190140095cNarayan Kamath ScopedUtfChars instruction_set(env, javaInstructionSet); 53620c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe if (env->ExceptionCheck()) { 537b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle return -1; 53820c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe } 53911d9f06a96a6909905c248ed684366190140095cNarayan Kamath 540c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe ScopedUtfChars target_compiler_filter(env, javaTargetCompilerFilter); 541c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe if (env->ExceptionCheck()) { 542c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe return -1; 54329d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe } 544c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe 545e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier return GetDexOptNeeded(env, 546e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier filename.c_str(), 547e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier instruction_set.c_str(), 548c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe target_compiler_filter.c_str(), 549c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe newProfile == JNI_TRUE); 55011d9f06a96a6909905c248ed684366190140095cNarayan Kamath} 55111d9f06a96a6909905c248ed684366190140095cNarayan Kamath 552b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle// public API 55311d9f06a96a6909905c248ed684366190140095cNarayan Kamathstatic jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) { 55406e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler ScopedUtfChars filename_utf(env, javaFilename); 55506e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler if (env->ExceptionCheck()) { 55606e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler return JNI_FALSE; 55706e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler } 55806e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler 55906e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler const char* filename = filename_utf.c_str(); 56006e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler if ((filename == nullptr) || !OS::FileExists(filename)) { 56106e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename << "' does not exist"; 56206e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException")); 56306e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler const char* message = (filename == nullptr) ? "<empty file name>" : filename; 56406e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler env->ThrowNew(fnfe.get(), message); 56506e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler return JNI_FALSE; 56606e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler } 56706e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler 568d1472a27e856ec68ab5a27abaaebe9c61d91d343Richard Uhler OatFileAssistant oat_file_assistant(filename, kRuntimeISA, false); 56906e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler return oat_file_assistant.IsUpToDate() ? JNI_FALSE : JNI_TRUE; 57039c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13Dave Allison} 57139c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13Dave Allison 572c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampestatic jboolean DexFile_isValidCompilerFilter(JNIEnv* env, 573c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe jclass javeDexFileClass ATTRIBUTE_UNUSED, 574c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe jstring javaCompilerFilter) { 575c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe ScopedUtfChars compiler_filter(env, javaCompilerFilter); 576c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe if (env->ExceptionCheck()) { 577c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe return -1; 578c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe } 579c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe 580c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe CompilerFilter::Filter filter; 581c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe return CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter) 582c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe ? JNI_TRUE : JNI_FALSE; 583c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe} 584c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe 585c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampestatic jboolean DexFile_isProfileGuidedCompilerFilter(JNIEnv* env, 586c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe jclass javeDexFileClass ATTRIBUTE_UNUSED, 587c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe jstring javaCompilerFilter) { 588c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe ScopedUtfChars compiler_filter(env, javaCompilerFilter); 589c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe if (env->ExceptionCheck()) { 590c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe return -1; 591c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe } 592c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe 593c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe CompilerFilter::Filter filter; 594c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) { 595c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe return JNI_FALSE; 596c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe } 597c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe return CompilerFilter::DependsOnProfile(filter) ? JNI_TRUE : JNI_FALSE; 598c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe} 599c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe 60086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampestatic jstring DexFile_getNonProfileGuidedCompilerFilter(JNIEnv* env, 60186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe jclass javeDexFileClass ATTRIBUTE_UNUSED, 60286a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe jstring javaCompilerFilter) { 60386a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe ScopedUtfChars compiler_filter(env, javaCompilerFilter); 60486a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe if (env->ExceptionCheck()) { 60586a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe return nullptr; 60686a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe } 60786a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe 60886a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe CompilerFilter::Filter filter; 60986a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) { 61086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe return javaCompilerFilter; 61186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe } 61286a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe 61386a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe CompilerFilter::Filter new_filter = CompilerFilter::GetNonProfileDependentFilterFrom(filter); 61486a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe 61586a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe // Filter stayed the same, return input. 61686a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe if (filter == new_filter) { 61786a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe return javaCompilerFilter; 61886a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe } 61986a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe 62086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe // Create a new string object and return. 62186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter); 62286a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe return env->NewStringUTF(new_filter_str.c_str()); 62386a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe} 62486a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe 625d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffraystatic jstring DexFile_getSafeModeCompilerFilter(JNIEnv* env, 626d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray jclass javeDexFileClass ATTRIBUTE_UNUSED, 627d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray jstring javaCompilerFilter) { 628d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray ScopedUtfChars compiler_filter(env, javaCompilerFilter); 629d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray if (env->ExceptionCheck()) { 630d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray return nullptr; 631d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray } 632d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray 633d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray CompilerFilter::Filter filter; 634d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) { 635d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray return javaCompilerFilter; 636d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray } 637d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray 638d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray CompilerFilter::Filter new_filter = CompilerFilter::GetSafeModeFilterFrom(filter); 639d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray 640d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray // Filter stayed the same, return input. 641d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray if (filter == new_filter) { 642d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray return javaCompilerFilter; 643d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray } 644d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray 645d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray // Create a new string object and return. 646d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter); 647d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray return env->NewStringUTF(new_filter_str.c_str()); 648d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray} 649d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray 65090671be8ca352f96eaf4f3109334f2f516268201Jeff Haostatic jboolean DexFile_isBackedByOatFile(JNIEnv* env, jclass, jobject cookie) { 65190671be8ca352f96eaf4f3109334f2f516268201Jeff Hao const OatFile* oat_file = nullptr; 65290671be8ca352f96eaf4f3109334f2f516268201Jeff Hao std::vector<const DexFile*> dex_files; 65390671be8ca352f96eaf4f3109334f2f516268201Jeff Hao if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) { 65490671be8ca352f96eaf4f3109334f2f516268201Jeff Hao DCHECK(env->ExceptionCheck()); 65590671be8ca352f96eaf4f3109334f2f516268201Jeff Hao return false; 65690671be8ca352f96eaf4f3109334f2f516268201Jeff Hao } 65790671be8ca352f96eaf4f3109334f2f516268201Jeff Hao return oat_file != nullptr; 65890671be8ca352f96eaf4f3109334f2f516268201Jeff Hao} 65990671be8ca352f96eaf4f3109334f2f516268201Jeff Hao 660cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravlestatic jobjectArray DexFile_getDexFileOutputPaths(JNIEnv* env, 661b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra jclass, 662b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra jstring javaFilename, 663b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra jstring javaInstructionSet) { 664b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra ScopedUtfChars filename(env, javaFilename); 665b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra if (env->ExceptionCheck()) { 666b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra return nullptr; 667b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra } 668b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra 669b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra ScopedUtfChars instruction_set(env, javaInstructionSet); 670b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra if (env->ExceptionCheck()) { 671b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra return nullptr; 672b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra } 673b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra 674b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra const InstructionSet target_instruction_set = GetInstructionSetFromString( 675b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra instruction_set.c_str()); 676b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra if (target_instruction_set == kNone) { 677b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException")); 678b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str())); 679b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra env->ThrowNew(iae.get(), message.c_str()); 680b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra return nullptr; 681b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra } 682b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra 683b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra OatFileAssistant oat_file_assistant(filename.c_str(), 684b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra target_instruction_set, 685b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra false /* load_executable */); 686b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra 687b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra std::unique_ptr<OatFile> best_oat_file = oat_file_assistant.GetBestOatFile(); 688b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra if (best_oat_file == nullptr) { 689b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra return nullptr; 690b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra } 691b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra 692cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle std::string oat_filename = best_oat_file->GetLocation(); 693cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle std::string vdex_filename = GetVdexFilename(best_oat_file->GetLocation()); 694cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle 695cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle ScopedLocalRef<jstring> jvdexFilename(env, env->NewStringUTF(vdex_filename.c_str())); 696cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle if (jvdexFilename.get() == nullptr) { 697cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle return nullptr; 698cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle } 699cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle ScopedLocalRef<jstring> joatFilename(env, env->NewStringUTF(oat_filename.c_str())); 700cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle if (joatFilename.get() == nullptr) { 701cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle return nullptr; 702cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle } 703cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle 704cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle // Now create output array and copy the set into it. 705cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle jobjectArray result = env->NewObjectArray(2, 706cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle WellKnownClasses::java_lang_String, 707cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle nullptr); 708cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle env->SetObjectArrayElement(result, 0, jvdexFilename.get()); 709cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle env->SetObjectArrayElement(result, 1, joatFilename.get()); 710cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle 711cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle return result; 712b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra} 713b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra 714f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromstatic JNINativeMethod gMethods[] = { 7151d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)Z"), 71600310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier NATIVE_METHOD(DexFile, 71700310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier defineClassNative, 71800310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier "(Ljava/lang/String;" 71900310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier "Ljava/lang/ClassLoader;" 72000310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier "Ljava/lang/Object;" 72100310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier "Ldalvik/system/DexFile;" 72200310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier ")Ljava/lang/Class;"), 723324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"), 724f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"), 7252cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier NATIVE_METHOD(DexFile, getDexOptNeeded, 726c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I"), 7272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier NATIVE_METHOD(DexFile, openDexFileNative, 728689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier "(Ljava/lang/String;" 729689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier "Ljava/lang/String;" 730689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier "I" 731689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier "Ljava/lang/ClassLoader;" 732689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier "[Ldalvik/system/DexPathList$Element;" 733689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier ")Ljava/lang/Object;"), 734ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light NATIVE_METHOD(DexFile, createCookieWithDirectBuffer, 735ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light "(Ljava/nio/ByteBuffer;II)Ljava/lang/Object;"), 736ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light NATIVE_METHOD(DexFile, createCookieWithArray, "([BII)Ljava/lang/Object;"), 737c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe NATIVE_METHOD(DexFile, isValidCompilerFilter, "(Ljava/lang/String;)Z"), 738c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe NATIVE_METHOD(DexFile, isProfileGuidedCompilerFilter, "(Ljava/lang/String;)Z"), 73986a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe NATIVE_METHOD(DexFile, 74086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe getNonProfileGuidedCompilerFilter, 74186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe "(Ljava/lang/String;)Ljava/lang/String;"), 742d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray NATIVE_METHOD(DexFile, 743d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray getSafeModeCompilerFilter, 744d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray "(Ljava/lang/String;)Ljava/lang/String;"), 74590671be8ca352f96eaf4f3109334f2f516268201Jeff Hao NATIVE_METHOD(DexFile, isBackedByOatFile, "(Ljava/lang/Object;)Z"), 7468943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath NATIVE_METHOD(DexFile, getDexFileStatus, 747b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), 748cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle NATIVE_METHOD(DexFile, getDexFileOutputPaths, 749cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;") 750f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}; 751f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 752f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromvoid register_dalvik_system_DexFile(JNIEnv* env) { 753eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes REGISTER_NATIVE_METHODS("dalvik/system/DexFile"); 754f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom} 755f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom 756f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom} // namespace art 757