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/*
18 * java.lang.Runtime
19 */
20#include "Dalvik.h"
21#include "native/InternalNativePriv.h"
22
23#include <dlfcn.h>
24#include <limits.h>
25#include <unistd.h>
26
27/*
28 * public void gc()
29 *
30 * Initiate a gc.
31 */
32static void Dalvik_java_lang_Runtime_gc(const u4* args, JValue* pResult)
33{
34    UNUSED_PARAMETER(args);
35
36    dvmCollectGarbage();
37    RETURN_VOID();
38}
39
40/*
41 * private static void nativeExit(int code)
42 *
43 * Runtime.exit() calls this after doing shutdown processing.  Runtime.halt()
44 * uses this as well.
45 */
46static void Dalvik_java_lang_Runtime_nativeExit(const u4* args,
47    JValue* pResult)
48{
49    int status = args[0];
50    if (gDvm.exitHook != NULL) {
51        dvmChangeStatus(NULL, THREAD_NATIVE);
52        (*gDvm.exitHook)(status);     // not expected to return
53        dvmChangeStatus(NULL, THREAD_RUNNING);
54        ALOGW("JNI exit hook returned");
55    }
56#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
57    dvmCompilerDumpStats();
58#endif
59    ALOGD("Calling exit(%d)", status);
60    exit(status);
61}
62
63/*
64 * static String nativeLoad(String filename, ClassLoader loader, String ldLibraryPath)
65 *
66 * Load the specified full path as a dynamic library filled with
67 * JNI-compatible methods. Returns null on success, or a failure
68 * message on failure.
69 */
70static void Dalvik_java_lang_Runtime_nativeLoad(const u4* args,
71    JValue* pResult)
72{
73    StringObject* fileNameObj = (StringObject*) args[0];
74    Object* classLoader = (Object*) args[1];
75    StringObject* ldLibraryPathObj = (StringObject*) args[2];
76
77    assert(fileNameObj != NULL);
78    char* fileName = dvmCreateCstrFromString(fileNameObj);
79
80    if (ldLibraryPathObj != NULL) {
81        char* ldLibraryPath = dvmCreateCstrFromString(ldLibraryPathObj);
82        void* sym = dlsym(RTLD_DEFAULT, "android_update_LD_LIBRARY_PATH");
83        if (sym != NULL) {
84            typedef void (*Fn)(const char*);
85            Fn android_update_LD_LIBRARY_PATH = reinterpret_cast<Fn>(sym);
86            (*android_update_LD_LIBRARY_PATH)(ldLibraryPath);
87        } else {
88            ALOGE("android_update_LD_LIBRARY_PATH not found; .so dependencies will not work!");
89        }
90        free(ldLibraryPath);
91    }
92
93    StringObject* result = NULL;
94    char* reason = NULL;
95    bool success = dvmLoadNativeCode(fileName, classLoader, &reason);
96    if (!success) {
97        const char* msg = (reason != NULL) ? reason : "unknown failure";
98        result = dvmCreateStringFromCstr(msg);
99        dvmReleaseTrackedAlloc((Object*) result, NULL);
100    }
101
102    free(reason);
103    free(fileName);
104    RETURN_PTR(result);
105}
106
107/*
108 * public long maxMemory()
109 *
110 * Returns GC heap max memory in bytes.
111 */
112static void Dalvik_java_lang_Runtime_maxMemory(const u4* args, JValue* pResult)
113{
114    RETURN_LONG(dvmGetHeapDebugInfo(kVirtualHeapMaximumSize));
115}
116
117/*
118 * public long totalMemory()
119 *
120 * Returns GC heap total memory in bytes.
121 */
122static void Dalvik_java_lang_Runtime_totalMemory(const u4* args,
123    JValue* pResult)
124{
125    RETURN_LONG(dvmGetHeapDebugInfo(kVirtualHeapSize));
126}
127
128/*
129 * public long freeMemory()
130 *
131 * Returns GC heap free memory in bytes.
132 */
133static void Dalvik_java_lang_Runtime_freeMemory(const u4* args,
134    JValue* pResult)
135{
136    size_t size = dvmGetHeapDebugInfo(kVirtualHeapSize);
137    size_t allocated = dvmGetHeapDebugInfo(kVirtualHeapAllocated);
138    long long result = size - allocated;
139    if (result < 0) {
140        result = 0;
141    }
142    RETURN_LONG(result);
143}
144
145const DalvikNativeMethod dvm_java_lang_Runtime[] = {
146    { "freeMemory",          "()J",
147        Dalvik_java_lang_Runtime_freeMemory },
148    { "gc",                 "()V",
149        Dalvik_java_lang_Runtime_gc },
150    { "maxMemory",          "()J",
151        Dalvik_java_lang_Runtime_maxMemory },
152    { "nativeExit",         "(I)V",
153        Dalvik_java_lang_Runtime_nativeExit },
154    { "nativeLoad",         "(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String;",
155        Dalvik_java_lang_Runtime_nativeLoad },
156    { "totalMemory",          "()J",
157        Dalvik_java_lang_Runtime_totalMemory },
158    { NULL, NULL, NULL },
159};
160