1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "dalvik_system_VMRuntime.h"
18 
19 #ifdef HAVE_ANDROID_OS
20 extern "C" void android_set_application_target_sdk_version(uint32_t version);
21 #endif
22 #include <limits.h>
23 #include <ScopedUtfChars.h>
24 
25 #pragma GCC diagnostic push
26 #pragma GCC diagnostic ignored "-Wshadow"
27 #include "toStringArray.h"
28 #pragma GCC diagnostic pop
29 
30 #include "art_method-inl.h"
31 #include "arch/instruction_set.h"
32 #include "class_linker-inl.h"
33 #include "common_throws.h"
34 #include "debugger.h"
35 #include "dex_file-inl.h"
36 #include "gc/accounting/card_table-inl.h"
37 #include "gc/allocator/dlmalloc.h"
38 #include "gc/heap.h"
39 #include "gc/space/dlmalloc_space.h"
40 #include "gc/space/image_space.h"
41 #include "gc/task_processor.h"
42 #include "intern_table.h"
43 #include "jni_internal.h"
44 #include "mirror/class-inl.h"
45 #include "mirror/dex_cache-inl.h"
46 #include "mirror/object-inl.h"
47 #include "runtime.h"
48 #include "scoped_fast_native_object_access.h"
49 #include "scoped_thread_state_change.h"
50 #include "thread.h"
51 #include "thread_list.h"
52 
53 namespace art {
54 
VMRuntime_getTargetHeapUtilization(JNIEnv *,jobject)55 static jfloat VMRuntime_getTargetHeapUtilization(JNIEnv*, jobject) {
56   return Runtime::Current()->GetHeap()->GetTargetHeapUtilization();
57 }
58 
VMRuntime_nativeSetTargetHeapUtilization(JNIEnv *,jobject,jfloat target)59 static void VMRuntime_nativeSetTargetHeapUtilization(JNIEnv*, jobject, jfloat target) {
60   Runtime::Current()->GetHeap()->SetTargetHeapUtilization(target);
61 }
62 
VMRuntime_startJitCompilation(JNIEnv *,jobject)63 static void VMRuntime_startJitCompilation(JNIEnv*, jobject) {
64 }
65 
VMRuntime_disableJitCompilation(JNIEnv *,jobject)66 static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) {
67 }
68 
VMRuntime_newNonMovableArray(JNIEnv * env,jobject,jclass javaElementClass,jint length)69 static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass,
70                                             jint length) {
71   ScopedFastNativeObjectAccess soa(env);
72   if (UNLIKELY(length < 0)) {
73     ThrowNegativeArraySizeException(length);
74     return nullptr;
75   }
76   mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
77   if (UNLIKELY(element_class == nullptr)) {
78     ThrowNullPointerException("element class == null");
79     return nullptr;
80   }
81   Runtime* runtime = Runtime::Current();
82   mirror::Class* array_class =
83       runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
84   if (UNLIKELY(array_class == nullptr)) {
85     return nullptr;
86   }
87   gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentNonMovingAllocator();
88   mirror::Array* result = mirror::Array::Alloc<true>(soa.Self(), array_class, length,
89                                                      array_class->GetComponentSizeShift(),
90                                                      allocator);
91   return soa.AddLocalReference<jobject>(result);
92 }
93 
VMRuntime_newUnpaddedArray(JNIEnv * env,jobject,jclass javaElementClass,jint length)94 static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaElementClass,
95                                           jint length) {
96   ScopedFastNativeObjectAccess soa(env);
97   if (UNLIKELY(length < 0)) {
98     ThrowNegativeArraySizeException(length);
99     return nullptr;
100   }
101   mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
102   if (UNLIKELY(element_class == nullptr)) {
103     ThrowNullPointerException("element class == null");
104     return nullptr;
105   }
106   Runtime* runtime = Runtime::Current();
107   mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(),
108                                                                          &element_class);
109   if (UNLIKELY(array_class == nullptr)) {
110     return nullptr;
111   }
112   gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
113   mirror::Array* result = mirror::Array::Alloc<true, true>(soa.Self(), array_class, length,
114                                                            array_class->GetComponentSizeShift(),
115                                                            allocator);
116   return soa.AddLocalReference<jobject>(result);
117 }
118 
VMRuntime_addressOf(JNIEnv * env,jobject,jobject javaArray)119 static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
120   if (javaArray == nullptr) {  // Most likely allocation failed
121     return 0;
122   }
123   ScopedFastNativeObjectAccess soa(env);
124   mirror::Array* array = soa.Decode<mirror::Array*>(javaArray);
125   if (!array->IsArrayInstance()) {
126     ThrowIllegalArgumentException("not an array");
127     return 0;
128   }
129   if (Runtime::Current()->GetHeap()->IsMovableObject(array)) {
130     ThrowRuntimeException("Trying to get address of movable array object");
131     return 0;
132   }
133   return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize(), 0));
134 }
135 
VMRuntime_clearGrowthLimit(JNIEnv *,jobject)136 static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) {
137   Runtime::Current()->GetHeap()->ClearGrowthLimit();
138 }
139 
VMRuntime_clampGrowthLimit(JNIEnv *,jobject)140 static void VMRuntime_clampGrowthLimit(JNIEnv*, jobject) {
141   Runtime::Current()->GetHeap()->ClampGrowthLimit();
142 }
143 
VMRuntime_isDebuggerActive(JNIEnv *,jobject)144 static jboolean VMRuntime_isDebuggerActive(JNIEnv*, jobject) {
145   return Dbg::IsDebuggerActive();
146 }
147 
VMRuntime_properties(JNIEnv * env,jobject)148 static jobjectArray VMRuntime_properties(JNIEnv* env, jobject) {
149   return toStringArray(env, Runtime::Current()->GetProperties());
150 }
151 
152 // This is for backward compatibility with dalvik which returned the
153 // meaningless "." when no boot classpath or classpath was
154 // specified. Unfortunately, some tests were using java.class.path to
155 // lookup relative file locations, so they are counting on this to be
156 // ".", presumably some applications or libraries could have as well.
DefaultToDot(const std::string & class_path)157 static const char* DefaultToDot(const std::string& class_path) {
158   return class_path.empty() ? "." : class_path.c_str();
159 }
160 
VMRuntime_bootClassPath(JNIEnv * env,jobject)161 static jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) {
162   return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPathString()));
163 }
164 
VMRuntime_classPath(JNIEnv * env,jobject)165 static jstring VMRuntime_classPath(JNIEnv* env, jobject) {
166   return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPathString()));
167 }
168 
VMRuntime_vmVersion(JNIEnv * env,jobject)169 static jstring VMRuntime_vmVersion(JNIEnv* env, jobject) {
170   return env->NewStringUTF(Runtime::GetVersion());
171 }
172 
VMRuntime_vmLibrary(JNIEnv * env,jobject)173 static jstring VMRuntime_vmLibrary(JNIEnv* env, jobject) {
174   return env->NewStringUTF(kIsDebugBuild ? "libartd.so" : "libart.so");
175 }
176 
VMRuntime_vmInstructionSet(JNIEnv * env,jobject)177 static jstring VMRuntime_vmInstructionSet(JNIEnv* env, jobject) {
178   InstructionSet isa = Runtime::Current()->GetInstructionSet();
179   const char* isa_string = GetInstructionSetString(isa);
180   return env->NewStringUTF(isa_string);
181 }
182 
VMRuntime_is64Bit(JNIEnv *,jobject)183 static jboolean VMRuntime_is64Bit(JNIEnv*, jobject) {
184   bool is64BitMode = (sizeof(void*) == sizeof(uint64_t));
185   return is64BitMode ? JNI_TRUE : JNI_FALSE;
186 }
187 
VMRuntime_isCheckJniEnabled(JNIEnv * env,jobject)188 static jboolean VMRuntime_isCheckJniEnabled(JNIEnv* env, jobject) {
189   return down_cast<JNIEnvExt*>(env)->vm->IsCheckJniEnabled() ? JNI_TRUE : JNI_FALSE;
190 }
191 
VMRuntime_setTargetSdkVersionNative(JNIEnv *,jobject,jint target_sdk_version)192 static void VMRuntime_setTargetSdkVersionNative(JNIEnv*, jobject, jint target_sdk_version) {
193   // This is the target SDK version of the app we're about to run. It is intended that this a place
194   // where workarounds can be enabled.
195   // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
196   // Note that targetSdkVersion may be 0, meaning "current".
197   Runtime::Current()->SetTargetSdkVersion(target_sdk_version);
198 
199 #ifdef HAVE_ANDROID_OS
200   // This part is letting libc/dynamic linker know about current app's
201   // target sdk version to enable compatibility workarounds.
202   android_set_application_target_sdk_version(static_cast<uint32_t>(target_sdk_version));
203 #endif
204 }
205 
VMRuntime_registerNativeAllocation(JNIEnv * env,jobject,jint bytes)206 static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) {
207   if (UNLIKELY(bytes < 0)) {
208     ScopedObjectAccess soa(env);
209     ThrowRuntimeException("allocation size negative %d", bytes);
210     return;
211   }
212   Runtime::Current()->GetHeap()->RegisterNativeAllocation(env, static_cast<size_t>(bytes));
213 }
214 
VMRuntime_registerNativeFree(JNIEnv * env,jobject,jint bytes)215 static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) {
216   if (UNLIKELY(bytes < 0)) {
217     ScopedObjectAccess soa(env);
218     ThrowRuntimeException("allocation size negative %d", bytes);
219     return;
220   }
221   Runtime::Current()->GetHeap()->RegisterNativeFree(env, static_cast<size_t>(bytes));
222 }
223 
VMRuntime_updateProcessState(JNIEnv *,jobject,jint process_state)224 static void VMRuntime_updateProcessState(JNIEnv*, jobject, jint process_state) {
225   Runtime* runtime = Runtime::Current();
226   runtime->GetHeap()->UpdateProcessState(static_cast<gc::ProcessState>(process_state));
227   runtime->UpdateProfilerState(process_state);
228 }
229 
VMRuntime_trimHeap(JNIEnv * env,jobject)230 static void VMRuntime_trimHeap(JNIEnv* env, jobject) {
231   Runtime::Current()->GetHeap()->Trim(ThreadForEnv(env));
232 }
233 
VMRuntime_concurrentGC(JNIEnv * env,jobject)234 static void VMRuntime_concurrentGC(JNIEnv* env, jobject) {
235   Runtime::Current()->GetHeap()->ConcurrentGC(ThreadForEnv(env), true);
236 }
237 
VMRuntime_requestHeapTrim(JNIEnv * env,jobject)238 static void VMRuntime_requestHeapTrim(JNIEnv* env, jobject) {
239   Runtime::Current()->GetHeap()->RequestTrim(ThreadForEnv(env));
240 }
241 
VMRuntime_requestConcurrentGC(JNIEnv * env,jobject)242 static void VMRuntime_requestConcurrentGC(JNIEnv* env, jobject) {
243   Runtime::Current()->GetHeap()->RequestConcurrentGC(ThreadForEnv(env), true);
244 }
245 
VMRuntime_startHeapTaskProcessor(JNIEnv * env,jobject)246 static void VMRuntime_startHeapTaskProcessor(JNIEnv* env, jobject) {
247   Runtime::Current()->GetHeap()->GetTaskProcessor()->Start(ThreadForEnv(env));
248 }
249 
VMRuntime_stopHeapTaskProcessor(JNIEnv * env,jobject)250 static void VMRuntime_stopHeapTaskProcessor(JNIEnv* env, jobject) {
251   Runtime::Current()->GetHeap()->GetTaskProcessor()->Stop(ThreadForEnv(env));
252 }
253 
VMRuntime_runHeapTasks(JNIEnv * env,jobject)254 static void VMRuntime_runHeapTasks(JNIEnv* env, jobject) {
255   Runtime::Current()->GetHeap()->GetTaskProcessor()->RunAllTasks(ThreadForEnv(env));
256 }
257 
258 typedef std::map<std::string, mirror::String*> StringTable;
259 
260 class PreloadDexCachesStringsVisitor : public SingleRootVisitor {
261  public:
PreloadDexCachesStringsVisitor(StringTable * table)262   explicit PreloadDexCachesStringsVisitor(StringTable* table) : table_(table) { }
263 
VisitRoot(mirror::Object * root,const RootInfo & info ATTRIBUTE_UNUSED)264   void VisitRoot(mirror::Object* root, const RootInfo& info ATTRIBUTE_UNUSED)
265       OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
266     mirror::String* string = root->AsString();
267     table_->operator[](string->ToModifiedUtf8()) = string;
268   }
269 
270  private:
271   StringTable* const table_;
272 };
273 
274 // Based on ClassLinker::ResolveString.
PreloadDexCachesResolveString(Handle<mirror::DexCache> dex_cache,uint32_t string_idx,StringTable & strings)275 static void PreloadDexCachesResolveString(
276     Handle<mirror::DexCache> dex_cache, uint32_t string_idx, StringTable& strings)
277     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
278   mirror::String* string = dex_cache->GetResolvedString(string_idx);
279   if (string != nullptr) {
280     return;
281   }
282   const DexFile* dex_file = dex_cache->GetDexFile();
283   const char* utf8 = dex_file->StringDataByIdx(string_idx);
284   string = strings[utf8];
285   if (string == nullptr) {
286     return;
287   }
288   // LOG(INFO) << "VMRuntime.preloadDexCaches resolved string=" << utf8;
289   dex_cache->SetResolvedString(string_idx, string);
290 }
291 
292 // Based on ClassLinker::ResolveType.
PreloadDexCachesResolveType(Thread * self,mirror::DexCache * dex_cache,uint32_t type_idx)293 static void PreloadDexCachesResolveType(
294     Thread* self, mirror::DexCache* dex_cache, uint32_t type_idx)
295     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
296   mirror::Class* klass = dex_cache->GetResolvedType(type_idx);
297   if (klass != nullptr) {
298     return;
299   }
300   const DexFile* dex_file = dex_cache->GetDexFile();
301   const char* class_name = dex_file->StringByTypeIdx(type_idx);
302   ClassLinker* linker = Runtime::Current()->GetClassLinker();
303   if (class_name[1] == '\0') {
304     klass = linker->FindPrimitiveClass(class_name[0]);
305   } else {
306     klass = linker->LookupClass(self, class_name, ComputeModifiedUtf8Hash(class_name), nullptr);
307   }
308   if (klass == nullptr) {
309     return;
310   }
311   // LOG(INFO) << "VMRuntime.preloadDexCaches resolved klass=" << class_name;
312   dex_cache->SetResolvedType(type_idx, klass);
313   // Skip uninitialized classes because filled static storage entry implies it is initialized.
314   if (!klass->IsInitialized()) {
315     // LOG(INFO) << "VMRuntime.preloadDexCaches uninitialized klass=" << class_name;
316     return;
317   }
318   // LOG(INFO) << "VMRuntime.preloadDexCaches static storage klass=" << class_name;
319 }
320 
321 // Based on ClassLinker::ResolveField.
PreloadDexCachesResolveField(Handle<mirror::DexCache> dex_cache,uint32_t field_idx,bool is_static)322 static void PreloadDexCachesResolveField(Handle<mirror::DexCache> dex_cache, uint32_t field_idx,
323                                          bool is_static)
324     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
325   ArtField* field = dex_cache->GetResolvedField(field_idx, sizeof(void*));
326   if (field != nullptr) {
327     return;
328   }
329   const DexFile* dex_file = dex_cache->GetDexFile();
330   const DexFile::FieldId& field_id = dex_file->GetFieldId(field_idx);
331   Thread* const self = Thread::Current();
332   StackHandleScope<1> hs(self);
333   Handle<mirror::Class> klass(hs.NewHandle(dex_cache->GetResolvedType(field_id.class_idx_)));
334   if (klass.Get() == nullptr) {
335     return;
336   }
337   if (is_static) {
338     field = mirror::Class::FindStaticField(self, klass, dex_cache.Get(), field_idx);
339   } else {
340     field = klass->FindInstanceField(dex_cache.Get(), field_idx);
341   }
342   if (field == nullptr) {
343     return;
344   }
345   // LOG(INFO) << "VMRuntime.preloadDexCaches resolved field " << PrettyField(field);
346   dex_cache->SetResolvedField(field_idx, field, sizeof(void*));
347 }
348 
349 // Based on ClassLinker::ResolveMethod.
PreloadDexCachesResolveMethod(Handle<mirror::DexCache> dex_cache,uint32_t method_idx,InvokeType invoke_type)350 static void PreloadDexCachesResolveMethod(Handle<mirror::DexCache> dex_cache, uint32_t method_idx,
351                                           InvokeType invoke_type)
352     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
353   ArtMethod* method = dex_cache->GetResolvedMethod(method_idx, sizeof(void*));
354   if (method != nullptr) {
355     return;
356   }
357   const DexFile* dex_file = dex_cache->GetDexFile();
358   const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
359   mirror::Class* klass = dex_cache->GetResolvedType(method_id.class_idx_);
360   if (klass == nullptr) {
361     return;
362   }
363   switch (invoke_type) {
364     case kDirect:
365     case kStatic:
366       method = klass->FindDirectMethod(dex_cache.Get(), method_idx, sizeof(void*));
367       break;
368     case kInterface:
369       method = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, sizeof(void*));
370       break;
371     case kSuper:
372     case kVirtual:
373       method = klass->FindVirtualMethod(dex_cache.Get(), method_idx, sizeof(void*));
374       break;
375     default:
376       LOG(FATAL) << "Unreachable - invocation type: " << invoke_type;
377       UNREACHABLE();
378   }
379   if (method == nullptr) {
380     return;
381   }
382   // LOG(INFO) << "VMRuntime.preloadDexCaches resolved method " << PrettyMethod(method);
383   dex_cache->SetResolvedMethod(method_idx, method, sizeof(void*));
384 }
385 
386 struct DexCacheStats {
387     uint32_t num_strings;
388     uint32_t num_types;
389     uint32_t num_fields;
390     uint32_t num_methods;
DexCacheStatsart::DexCacheStats391     DexCacheStats() : num_strings(0),
392                       num_types(0),
393                       num_fields(0),
394                       num_methods(0) {}
395 };
396 
397 static const bool kPreloadDexCachesEnabled = true;
398 
399 // Disabled because it takes a long time (extra half second) but
400 // gives almost no benefit in terms of saving private dirty pages.
401 static const bool kPreloadDexCachesStrings = false;
402 
403 static const bool kPreloadDexCachesTypes = true;
404 static const bool kPreloadDexCachesFieldsAndMethods = true;
405 
406 static const bool kPreloadDexCachesCollectStats = true;
407 
PreloadDexCachesStatsTotal(DexCacheStats * total)408 static void PreloadDexCachesStatsTotal(DexCacheStats* total) {
409   if (!kPreloadDexCachesCollectStats) {
410     return;
411   }
412 
413   ClassLinker* linker = Runtime::Current()->GetClassLinker();
414   const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
415   for (size_t i = 0; i< boot_class_path.size(); i++) {
416     const DexFile* dex_file = boot_class_path[i];
417     CHECK(dex_file != nullptr);
418     total->num_strings += dex_file->NumStringIds();
419     total->num_fields += dex_file->NumFieldIds();
420     total->num_methods += dex_file->NumMethodIds();
421     total->num_types += dex_file->NumTypeIds();
422   }
423 }
424 
PreloadDexCachesStatsFilled(DexCacheStats * filled)425 static void PreloadDexCachesStatsFilled(DexCacheStats* filled)
426     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
427   if (!kPreloadDexCachesCollectStats) {
428       return;
429   }
430   ClassLinker* linker = Runtime::Current()->GetClassLinker();
431   const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
432   for (size_t i = 0; i< boot_class_path.size(); i++) {
433     const DexFile* dex_file = boot_class_path[i];
434     CHECK(dex_file != nullptr);
435     mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file);
436     for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
437       mirror::String* string = dex_cache->GetResolvedString(j);
438       if (string != nullptr) {
439         filled->num_strings++;
440       }
441     }
442     for (size_t j = 0; j < dex_cache->NumResolvedTypes(); j++) {
443       mirror::Class* klass = dex_cache->GetResolvedType(j);
444       if (klass != nullptr) {
445         filled->num_types++;
446       }
447     }
448     for (size_t j = 0; j < dex_cache->NumResolvedFields(); j++) {
449       ArtField* field = linker->GetResolvedField(j, dex_cache);
450       if (field != nullptr) {
451         filled->num_fields++;
452       }
453     }
454     for (size_t j = 0; j < dex_cache->NumResolvedMethods(); j++) {
455       ArtMethod* method = dex_cache->GetResolvedMethod(j, sizeof(void*));
456       if (method != nullptr) {
457         filled->num_methods++;
458       }
459     }
460   }
461 }
462 
463 // TODO: http://b/11309598 This code was ported over based on the
464 // Dalvik version. However, ART has similar code in other places such
465 // as the CompilerDriver. This code could probably be refactored to
466 // serve both uses.
VMRuntime_preloadDexCaches(JNIEnv * env,jobject)467 static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
468   if (!kPreloadDexCachesEnabled) {
469     return;
470   }
471 
472   ScopedObjectAccess soa(env);
473 
474   DexCacheStats total;
475   DexCacheStats before;
476   if (kPreloadDexCachesCollectStats) {
477     LOG(INFO) << "VMRuntime.preloadDexCaches starting";
478     PreloadDexCachesStatsTotal(&total);
479     PreloadDexCachesStatsFilled(&before);
480   }
481 
482   Runtime* runtime = Runtime::Current();
483   ClassLinker* linker = runtime->GetClassLinker();
484 
485   // We use a std::map to avoid heap allocating StringObjects to lookup in gDvm.literalStrings
486   StringTable strings;
487   if (kPreloadDexCachesStrings) {
488     PreloadDexCachesStringsVisitor visitor(&strings);
489     runtime->GetInternTable()->VisitRoots(&visitor, kVisitRootFlagAllRoots);
490   }
491 
492   const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
493   for (size_t i = 0; i< boot_class_path.size(); i++) {
494     const DexFile* dex_file = boot_class_path[i];
495     CHECK(dex_file != nullptr);
496     StackHandleScope<1> hs(soa.Self());
497     Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file)));
498 
499     if (kPreloadDexCachesStrings) {
500       for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
501         PreloadDexCachesResolveString(dex_cache, j, strings);
502       }
503     }
504 
505     if (kPreloadDexCachesTypes) {
506       for (size_t j = 0; j < dex_cache->NumResolvedTypes(); j++) {
507         PreloadDexCachesResolveType(soa.Self(), dex_cache.Get(), j);
508       }
509     }
510 
511     if (kPreloadDexCachesFieldsAndMethods) {
512       for (size_t class_def_index = 0;
513            class_def_index < dex_file->NumClassDefs();
514            class_def_index++) {
515         const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
516         const uint8_t* class_data = dex_file->GetClassData(class_def);
517         if (class_data == nullptr) {
518           continue;
519         }
520         ClassDataItemIterator it(*dex_file, class_data);
521         for (; it.HasNextStaticField(); it.Next()) {
522           uint32_t field_idx = it.GetMemberIndex();
523           PreloadDexCachesResolveField(dex_cache, field_idx, true);
524         }
525         for (; it.HasNextInstanceField(); it.Next()) {
526           uint32_t field_idx = it.GetMemberIndex();
527           PreloadDexCachesResolveField(dex_cache, field_idx, false);
528         }
529         for (; it.HasNextDirectMethod(); it.Next()) {
530           uint32_t method_idx = it.GetMemberIndex();
531           InvokeType invoke_type = it.GetMethodInvokeType(class_def);
532           PreloadDexCachesResolveMethod(dex_cache, method_idx, invoke_type);
533         }
534         for (; it.HasNextVirtualMethod(); it.Next()) {
535           uint32_t method_idx = it.GetMemberIndex();
536           InvokeType invoke_type = it.GetMethodInvokeType(class_def);
537           PreloadDexCachesResolveMethod(dex_cache, method_idx, invoke_type);
538         }
539       }
540     }
541   }
542 
543   if (kPreloadDexCachesCollectStats) {
544     DexCacheStats after;
545     PreloadDexCachesStatsFilled(&after);
546     LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches strings total=%d before=%d after=%d",
547                               total.num_strings, before.num_strings, after.num_strings);
548     LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches types total=%d before=%d after=%d",
549                               total.num_types, before.num_types, after.num_types);
550     LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches fields total=%d before=%d after=%d",
551                               total.num_fields, before.num_fields, after.num_fields);
552     LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches methods total=%d before=%d after=%d",
553                               total.num_methods, before.num_methods, after.num_methods);
554     LOG(INFO) << StringPrintf("VMRuntime.preloadDexCaches finished");
555   }
556 }
557 
558 
559 /*
560  * This is called by the framework when it knows the application directory and
561  * process name.  We use this information to start up the sampling profiler for
562  * for ART.
563  */
VMRuntime_registerAppInfo(JNIEnv * env,jclass,jstring pkgName,jstring appDir ATTRIBUTE_UNUSED,jstring procName ATTRIBUTE_UNUSED)564 static void VMRuntime_registerAppInfo(JNIEnv* env, jclass, jstring pkgName,
565                                       jstring appDir ATTRIBUTE_UNUSED,
566                                       jstring procName ATTRIBUTE_UNUSED) {
567   const char *pkgNameChars = env->GetStringUTFChars(pkgName, nullptr);
568   std::string profileFile = StringPrintf("/data/dalvik-cache/profiles/%s", pkgNameChars);
569 
570   Runtime::Current()->StartProfiler(profileFile.c_str());
571 
572   env->ReleaseStringUTFChars(pkgName, pkgNameChars);
573 }
574 
VMRuntime_isBootClassPathOnDisk(JNIEnv * env,jclass,jstring java_instruction_set)575 static jboolean VMRuntime_isBootClassPathOnDisk(JNIEnv* env, jclass, jstring java_instruction_set) {
576   ScopedUtfChars instruction_set(env, java_instruction_set);
577   if (instruction_set.c_str() == nullptr) {
578     return JNI_FALSE;
579   }
580   InstructionSet isa = GetInstructionSetFromString(instruction_set.c_str());
581   if (isa == kNone) {
582     ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
583     std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
584     env->ThrowNew(iae.get(), message.c_str());
585     return JNI_FALSE;
586   }
587   std::string error_msg;
588   std::unique_ptr<ImageHeader> image_header(gc::space::ImageSpace::ReadImageHeader(
589       Runtime::Current()->GetImageLocation().c_str(), isa, &error_msg));
590   return image_header.get() != nullptr;
591 }
592 
VMRuntime_getCurrentInstructionSet(JNIEnv * env,jclass)593 static jstring VMRuntime_getCurrentInstructionSet(JNIEnv* env, jclass) {
594   return env->NewStringUTF(GetInstructionSetString(kRuntimeISA));
595 }
596 
597 static JNINativeMethod gMethods[] = {
598   NATIVE_METHOD(VMRuntime, addressOf, "!(Ljava/lang/Object;)J"),
599   NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"),
600   NATIVE_METHOD(VMRuntime, clampGrowthLimit, "()V"),
601   NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"),
602   NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"),
603   NATIVE_METHOD(VMRuntime, concurrentGC, "()V"),
604   NATIVE_METHOD(VMRuntime, disableJitCompilation, "()V"),
605   NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"),
606   NATIVE_METHOD(VMRuntime, isDebuggerActive, "!()Z"),
607   NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"),
608   NATIVE_METHOD(VMRuntime, newNonMovableArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"),
609   NATIVE_METHOD(VMRuntime, newUnpaddedArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"),
610   NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"),
611   NATIVE_METHOD(VMRuntime, setTargetSdkVersionNative, "(I)V"),
612   NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"),
613   NATIVE_METHOD(VMRuntime, registerNativeFree, "(I)V"),
614   NATIVE_METHOD(VMRuntime, requestConcurrentGC, "()V"),
615   NATIVE_METHOD(VMRuntime, requestHeapTrim, "()V"),
616   NATIVE_METHOD(VMRuntime, runHeapTasks, "()V"),
617   NATIVE_METHOD(VMRuntime, updateProcessState, "(I)V"),
618   NATIVE_METHOD(VMRuntime, startHeapTaskProcessor, "()V"),
619   NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"),
620   NATIVE_METHOD(VMRuntime, stopHeapTaskProcessor, "()V"),
621   NATIVE_METHOD(VMRuntime, trimHeap, "()V"),
622   NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"),
623   NATIVE_METHOD(VMRuntime, vmLibrary, "()Ljava/lang/String;"),
624   NATIVE_METHOD(VMRuntime, vmInstructionSet, "()Ljava/lang/String;"),
625   NATIVE_METHOD(VMRuntime, is64Bit, "!()Z"),
626   NATIVE_METHOD(VMRuntime, isCheckJniEnabled, "!()Z"),
627   NATIVE_METHOD(VMRuntime, preloadDexCaches, "()V"),
628   NATIVE_METHOD(VMRuntime, registerAppInfo,
629                 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"),
630   NATIVE_METHOD(VMRuntime, isBootClassPathOnDisk, "(Ljava/lang/String;)Z"),
631   NATIVE_METHOD(VMRuntime, getCurrentInstructionSet, "()Ljava/lang/String;"),
632 };
633 
register_dalvik_system_VMRuntime(JNIEnv * env)634 void register_dalvik_system_VMRuntime(JNIEnv* env) {
635   REGISTER_NATIVE_METHODS("dalvik/system/VMRuntime");
636 }
637 
638 }  // namespace art
639