| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <limits.h> |
| |
| #include "class_linker.h" |
| #include "common_throws.h" |
| #include "debugger.h" |
| #include "dex_file-inl.h" |
| #include "gc/allocator/dlmalloc.h" |
| #include "gc/heap.h" |
| #include "gc/space/dlmalloc_space.h" |
| #include "jni_internal.h" |
| #include "mirror/class-inl.h" |
| #include "mirror/object.h" |
| #include "mirror/object-inl.h" |
| #include "object_utils.h" |
| #include "scoped_thread_state_change.h" |
| #include "thread.h" |
| #include "thread_list.h" |
| #include "toStringArray.h" |
| |
| namespace art { |
| |
| static jfloat VMRuntime_getTargetHeapUtilization(JNIEnv*, jobject) { |
| return Runtime::Current()->GetHeap()->GetTargetHeapUtilization(); |
| } |
| |
| static void VMRuntime_nativeSetTargetHeapUtilization(JNIEnv*, jobject, jfloat target) { |
| Runtime::Current()->GetHeap()->SetTargetHeapUtilization(target); |
| } |
| |
| static void VMRuntime_startJitCompilation(JNIEnv*, jobject) { |
| } |
| |
| static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) { |
| } |
| |
| static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, jint length) { |
| ScopedObjectAccess soa(env); |
| #ifdef MOVING_GARBAGE_COLLECTOR |
| // TODO: right now, we don't have a copying collector, so there's no need |
| // to do anything special here, but we ought to pass the non-movability |
| // through to the allocator. |
| UNIMPLEMENTED(FATAL); |
| #endif |
| |
| mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass); |
| if (element_class == NULL) { |
| ThrowNullPointerException(NULL, "element class == null"); |
| return NULL; |
| } |
| if (length < 0) { |
| ThrowNegativeArraySizeException(length); |
| return NULL; |
| } |
| |
| ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); |
| std::string descriptor; |
| descriptor += "["; |
| descriptor += ClassHelper(element_class).GetDescriptor(); |
| mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL); |
| mirror::Array* result = mirror::Array::Alloc(soa.Self(), array_class, length); |
| if (result == NULL) { |
| return NULL; |
| } |
| return soa.AddLocalReference<jobject>(result); |
| } |
| |
| static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) { |
| if (javaArray == NULL) { // Most likely allocation failed |
| return 0; |
| } |
| ScopedObjectAccess soa(env); |
| mirror::Array* array = soa.Decode<mirror::Array*>(javaArray); |
| if (!array->IsArrayInstance()) { |
| ThrowIllegalArgumentException(NULL, "not an array"); |
| return 0; |
| } |
| // TODO: we should also check that this is a non-movable array. |
| return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize())); |
| } |
| |
| static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) { |
| Runtime::Current()->GetHeap()->ClearGrowthLimit(); |
| } |
| |
| static jboolean VMRuntime_isDebuggerActive(JNIEnv*, jobject) { |
| return Dbg::IsDebuggerActive(); |
| } |
| |
| static jobjectArray VMRuntime_properties(JNIEnv* env, jobject) { |
| return toStringArray(env, Runtime::Current()->GetProperties()); |
| } |
| |
| // This is for backward compatibility with dalvik which returned the |
| // meaningless "." when no boot classpath or classpath was |
| // specified. Unfortunately, some tests were using java.class.path to |
| // lookup relative file locations, so they are counting on this to be |
| // ".", presumably some applications or libraries could have as well. |
| static const char* DefaultToDot(const std::string& class_path) { |
| return class_path.empty() ? "." : class_path.c_str(); |
| } |
| |
| static jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) { |
| return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPathString())); |
| } |
| |
| static jstring VMRuntime_classPath(JNIEnv* env, jobject) { |
| return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPathString())); |
| } |
| |
| static jstring VMRuntime_vmVersion(JNIEnv* env, jobject) { |
| return env->NewStringUTF(Runtime::Current()->GetVersion()); |
| } |
| |
| static jstring VMRuntime_vmLibrary(JNIEnv* env, jobject) { |
| return env->NewStringUTF(kIsDebugBuild ? "libartd.so" : "libart.so"); |
| } |
| |
| static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVersion) { |
| // This is the target SDK version of the app we're about to run. |
| // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000). |
| // Note that targetSdkVersion may be 0, meaning "current". |
| if (targetSdkVersion > 0 && targetSdkVersion <= 13 /* honeycomb-mr2 */) { |
| Runtime* runtime = Runtime::Current(); |
| JavaVMExt* vm = runtime->GetJavaVM(); |
| if (vm->check_jni) { |
| LOG(INFO) << "CheckJNI enabled: not enabling JNI app bug workarounds."; |
| } else { |
| LOG(INFO) << "Turning on JNI app bug workarounds for target SDK version " |
| << targetSdkVersion << "..."; |
| |
| vm->work_around_app_jni_bugs = true; |
| } |
| } |
| } |
| |
| static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) { |
| ScopedObjectAccess soa(env); |
| if (bytes < 0) { |
| ThrowRuntimeException("allocation size negative %d", bytes); |
| return; |
| } |
| Runtime::Current()->GetHeap()->RegisterNativeAllocation(bytes); |
| } |
| |
| static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) { |
| ScopedObjectAccess soa(env); |
| if (bytes < 0) { |
| ThrowRuntimeException("allocation size negative %d", bytes); |
| return; |
| } |
| Runtime::Current()->GetHeap()->RegisterNativeFree(bytes); |
| } |
| |
| static void VMRuntime_trimHeap(JNIEnv*, jobject) { |
| uint64_t start_ns = NanoTime(); |
| |
| // Trim the managed heap. |
| gc::Heap* heap = Runtime::Current()->GetHeap(); |
| gc::space::DlMallocSpace* alloc_space = heap->GetAllocSpace(); |
| size_t alloc_space_size = alloc_space->Size(); |
| float managed_utilization = |
| static_cast<float>(alloc_space->GetBytesAllocated()) / alloc_space_size; |
| size_t managed_reclaimed = heap->Trim(); |
| |
| uint64_t gc_heap_end_ns = NanoTime(); |
| |
| // Trim the native heap. |
| dlmalloc_trim(0); |
| size_t native_reclaimed = 0; |
| dlmalloc_inspect_all(DlmallocMadviseCallback, &native_reclaimed); |
| |
| uint64_t end_ns = NanoTime(); |
| |
| LOG(INFO) << "Heap trim of managed (duration=" << PrettyDuration(gc_heap_end_ns - start_ns) |
| << ", advised=" << PrettySize(managed_reclaimed) << ") and native (duration=" |
| << PrettyDuration(end_ns - gc_heap_end_ns) << ", advised=" << PrettySize(native_reclaimed) |
| << ") heaps. Managed heap utilization of " << static_cast<int>(100 * managed_utilization) |
| << "%."; |
| } |
| |
| static void VMRuntime_concurrentGC(JNIEnv* env, jobject) { |
| Thread* self = static_cast<JNIEnvExt*>(env)->self; |
| Runtime::Current()->GetHeap()->ConcurrentGC(self); |
| } |
| |
| static JNINativeMethod gMethods[] = { |
| NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"), |
| NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"), |
| NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"), |
| NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"), |
| NATIVE_METHOD(VMRuntime, concurrentGC, "()V"), |
| NATIVE_METHOD(VMRuntime, disableJitCompilation, "()V"), |
| NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"), |
| NATIVE_METHOD(VMRuntime, isDebuggerActive, "()Z"), |
| NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"), |
| NATIVE_METHOD(VMRuntime, newNonMovableArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"), |
| NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"), |
| NATIVE_METHOD(VMRuntime, setTargetSdkVersion, "(I)V"), |
| NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"), |
| NATIVE_METHOD(VMRuntime, registerNativeFree, "(I)V"), |
| NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"), |
| NATIVE_METHOD(VMRuntime, trimHeap, "()V"), |
| NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"), |
| NATIVE_METHOD(VMRuntime, vmLibrary, "()Ljava/lang/String;"), |
| }; |
| |
| void register_dalvik_system_VMRuntime(JNIEnv* env) { |
| REGISTER_NATIVE_METHODS("dalvik/system/VMRuntime"); |
| } |
| |
| } // namespace art |