Home | History | Annotate | Download | only in native
      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 <limits.h>
     18 
     19 #include "class_linker.h"
     20 #include "common_throws.h"
     21 #include "debugger.h"
     22 #include "dex_file-inl.h"
     23 #include "gc/allocator/dlmalloc.h"
     24 #include "gc/heap.h"
     25 #include "gc/space/dlmalloc_space.h"
     26 #include "jni_internal.h"
     27 #include "mirror/class-inl.h"
     28 #include "mirror/object.h"
     29 #include "mirror/object-inl.h"
     30 #include "object_utils.h"
     31 #include "scoped_thread_state_change.h"
     32 #include "thread.h"
     33 #include "thread_list.h"
     34 #include "toStringArray.h"
     35 
     36 namespace art {
     37 
     38 static jfloat VMRuntime_getTargetHeapUtilization(JNIEnv*, jobject) {
     39   return Runtime::Current()->GetHeap()->GetTargetHeapUtilization();
     40 }
     41 
     42 static void VMRuntime_nativeSetTargetHeapUtilization(JNIEnv*, jobject, jfloat target) {
     43   Runtime::Current()->GetHeap()->SetTargetHeapUtilization(target);
     44 }
     45 
     46 static void VMRuntime_startJitCompilation(JNIEnv*, jobject) {
     47 }
     48 
     49 static void VMRuntime_disableJitCompilation(JNIEnv*, jobject) {
     50 }
     51 
     52 static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass, jint length) {
     53   ScopedObjectAccess soa(env);
     54 #ifdef MOVING_GARBAGE_COLLECTOR
     55   // TODO: right now, we don't have a copying collector, so there's no need
     56   // to do anything special here, but we ought to pass the non-movability
     57   // through to the allocator.
     58   UNIMPLEMENTED(FATAL);
     59 #endif
     60 
     61   mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
     62   if (element_class == NULL) {
     63     ThrowNullPointerException(NULL, "element class == null");
     64     return NULL;
     65   }
     66   if (length < 0) {
     67     ThrowNegativeArraySizeException(length);
     68     return NULL;
     69   }
     70 
     71   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     72   std::string descriptor;
     73   descriptor += "[";
     74   descriptor += ClassHelper(element_class).GetDescriptor();
     75   mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL);
     76   mirror::Array* result = mirror::Array::Alloc(soa.Self(), array_class, length);
     77   return soa.AddLocalReference<jobject>(result);
     78 }
     79 
     80 static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
     81   if (javaArray == NULL) {  // Most likely allocation failed
     82     return 0;
     83   }
     84   ScopedObjectAccess soa(env);
     85   mirror::Array* array = soa.Decode<mirror::Array*>(javaArray);
     86   if (!array->IsArrayInstance()) {
     87     ThrowIllegalArgumentException(NULL, "not an array");
     88     return 0;
     89   }
     90   // TODO: we should also check that this is a non-movable array.
     91   return reinterpret_cast<uintptr_t>(array->GetRawData(array->GetClass()->GetComponentSize()));
     92 }
     93 
     94 static void VMRuntime_clearGrowthLimit(JNIEnv*, jobject) {
     95   Runtime::Current()->GetHeap()->ClearGrowthLimit();
     96 }
     97 
     98 static jboolean VMRuntime_isDebuggerActive(JNIEnv*, jobject) {
     99   return Dbg::IsDebuggerActive();
    100 }
    101 
    102 static jobjectArray VMRuntime_properties(JNIEnv* env, jobject) {
    103   return toStringArray(env, Runtime::Current()->GetProperties());
    104 }
    105 
    106 // This is for backward compatibility with dalvik which returned the
    107 // meaningless "." when no boot classpath or classpath was
    108 // specified. Unfortunately, some tests were using java.class.path to
    109 // lookup relative file locations, so they are counting on this to be
    110 // ".", presumably some applications or libraries could have as well.
    111 static const char* DefaultToDot(const std::string& class_path) {
    112   return class_path.empty() ? "." : class_path.c_str();
    113 }
    114 
    115 static jstring VMRuntime_bootClassPath(JNIEnv* env, jobject) {
    116   return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetBootClassPathString()));
    117 }
    118 
    119 static jstring VMRuntime_classPath(JNIEnv* env, jobject) {
    120   return env->NewStringUTF(DefaultToDot(Runtime::Current()->GetClassPathString()));
    121 }
    122 
    123 static jstring VMRuntime_vmVersion(JNIEnv* env, jobject) {
    124   return env->NewStringUTF(Runtime::Current()->GetVersion());
    125 }
    126 
    127 static jstring VMRuntime_vmLibrary(JNIEnv* env, jobject) {
    128   return env->NewStringUTF(kIsDebugBuild ? "libartd.so" : "libart.so");
    129 }
    130 
    131 static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVersion) {
    132   // This is the target SDK version of the app we're about to run.
    133   // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000).
    134   // Note that targetSdkVersion may be 0, meaning "current".
    135   if (targetSdkVersion > 0 && targetSdkVersion <= 13 /* honeycomb-mr2 */) {
    136     Runtime* runtime = Runtime::Current();
    137     JavaVMExt* vm = runtime->GetJavaVM();
    138     if (vm->check_jni) {
    139       LOG(INFO) << "CheckJNI enabled: not enabling JNI app bug workarounds.";
    140     } else {
    141       LOG(INFO) << "Turning on JNI app bug workarounds for target SDK version "
    142           << targetSdkVersion << "...";
    143 
    144       vm->work_around_app_jni_bugs = true;
    145     }
    146   }
    147 }
    148 
    149 static void VMRuntime_registerNativeAllocation(JNIEnv* env, jobject, jint bytes) {
    150   ScopedObjectAccess soa(env);
    151   if (bytes < 0) {
    152     ThrowRuntimeException("allocation size negative %d", bytes);
    153     return;
    154   }
    155   Runtime::Current()->GetHeap()->RegisterNativeAllocation(bytes);
    156 }
    157 
    158 static void VMRuntime_registerNativeFree(JNIEnv* env, jobject, jint bytes) {
    159   ScopedObjectAccess soa(env);
    160   if (bytes < 0) {
    161     ThrowRuntimeException("allocation size negative %d", bytes);
    162     return;
    163   }
    164   Runtime::Current()->GetHeap()->RegisterNativeFree(bytes);
    165 }
    166 
    167 static void VMRuntime_trimHeap(JNIEnv*, jobject) {
    168   uint64_t start_ns = NanoTime();
    169 
    170   // Trim the managed heap.
    171   gc::Heap* heap = Runtime::Current()->GetHeap();
    172   gc::space::DlMallocSpace* alloc_space = heap->GetAllocSpace();
    173   size_t alloc_space_size = alloc_space->Size();
    174   float managed_utilization =
    175       static_cast<float>(alloc_space->GetBytesAllocated()) / alloc_space_size;
    176   size_t managed_reclaimed = heap->Trim();
    177 
    178   uint64_t gc_heap_end_ns = NanoTime();
    179 
    180   // Trim the native heap.
    181   dlmalloc_trim(0);
    182   size_t native_reclaimed = 0;
    183   dlmalloc_inspect_all(DlmallocMadviseCallback, &native_reclaimed);
    184 
    185   uint64_t end_ns = NanoTime();
    186 
    187   LOG(INFO) << "Heap trim of managed (duration=" << PrettyDuration(gc_heap_end_ns - start_ns)
    188       << ", advised=" << PrettySize(managed_reclaimed) << ") and native (duration="
    189       << PrettyDuration(end_ns - gc_heap_end_ns) << ", advised=" << PrettySize(native_reclaimed)
    190       << ") heaps. Managed heap utilization of " << static_cast<int>(100 * managed_utilization)
    191       << "%.";
    192 }
    193 
    194 static void VMRuntime_concurrentGC(JNIEnv* env, jobject) {
    195   Thread* self = static_cast<JNIEnvExt*>(env)->self;
    196   Runtime::Current()->GetHeap()->ConcurrentGC(self);
    197 }
    198 
    199 static JNINativeMethod gMethods[] = {
    200   NATIVE_METHOD(VMRuntime, addressOf, "(Ljava/lang/Object;)J"),
    201   NATIVE_METHOD(VMRuntime, bootClassPath, "()Ljava/lang/String;"),
    202   NATIVE_METHOD(VMRuntime, classPath, "()Ljava/lang/String;"),
    203   NATIVE_METHOD(VMRuntime, clearGrowthLimit, "()V"),
    204   NATIVE_METHOD(VMRuntime, concurrentGC, "()V"),
    205   NATIVE_METHOD(VMRuntime, disableJitCompilation, "()V"),
    206   NATIVE_METHOD(VMRuntime, getTargetHeapUtilization, "()F"),
    207   NATIVE_METHOD(VMRuntime, isDebuggerActive, "()Z"),
    208   NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"),
    209   NATIVE_METHOD(VMRuntime, newNonMovableArray, "(Ljava/lang/Class;I)Ljava/lang/Object;"),
    210   NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"),
    211   NATIVE_METHOD(VMRuntime, setTargetSdkVersion, "(I)V"),
    212   NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"),
    213   NATIVE_METHOD(VMRuntime, registerNativeFree, "(I)V"),
    214   NATIVE_METHOD(VMRuntime, startJitCompilation, "()V"),
    215   NATIVE_METHOD(VMRuntime, trimHeap, "()V"),
    216   NATIVE_METHOD(VMRuntime, vmVersion, "()Ljava/lang/String;"),
    217   NATIVE_METHOD(VMRuntime, vmLibrary, "()Ljava/lang/String;"),
    218 };
    219 
    220 void register_dalvik_system_VMRuntime(JNIEnv* env) {
    221   REGISTER_NATIVE_METHODS("dalvik/system/VMRuntime");
    222 }
    223 
    224 }  // namespace art
    225