blob: 08277f07e964dbfb1a4c6cda9df844987a3156e4 [file] [log] [blame]
Brian Carlstromb2acfa22013-06-19 15:09:28 -07001/*
2 * Copyright (C) 2013 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 "JniInvocation.h"
18
19#include <dlfcn.h>
20#include <stdlib.h>
21
22#include <cstddef>
23
24#define LOG_TAG "JniInvocation"
25#include "cutils/log.h"
26
27#ifdef HAVE_ANDROID_OS
28#include "cutils/properties.h"
29#endif
30
31JniInvocation* JniInvocation::jni_invocation_ = NULL;
32
33JniInvocation::JniInvocation() :
34 handle_(NULL),
35 JNI_GetDefaultJavaVMInitArgs_(NULL),
36 JNI_CreateJavaVM_(NULL),
37 JNI_GetCreatedJavaVMs_(NULL) {
38
39 LOG_ALWAYS_FATAL_IF(jni_invocation_ != NULL, "JniInvocation instance already initialized");
40 jni_invocation_ = this;
41}
42
43JniInvocation::~JniInvocation() {
44 jni_invocation_ = NULL;
45 if (handle_ != NULL) {
46 dlclose(handle_);
47 }
48}
49
50bool JniInvocation::Init(const char* library) {
51#ifdef HAVE_ANDROID_OS
52 char default_library[PROPERTY_VALUE_MAX];
53 property_get("dalvik.vm.lib", default_library, "libdvm.so");
54#else
55 const char* default_library = "libdvm.so";
56#endif
57 if (library == NULL) {
58 library = default_library;
59 }
60
61 handle_ = dlopen(library, RTLD_NOW);
62 if (handle_ == NULL) {
63 ALOGE("Failed to dlopen %s: %s", library, dlerror());
64 return false;
65 }
66 if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
67 "JNI_GetDefaultJavaVMInitArgs")) {
68 return false;
69 }
70 if (!FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
71 "JNI_CreateJavaVM")) {
72 return false;
73 }
74 if (!FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
75 "JNI_GetCreatedJavaVMs")) {
76 return false;
77 }
78 return true;
79}
80
81jint JniInvocation::JNI_GetDefaultJavaVMInitArgs(void* vmargs) {
82 return JNI_GetDefaultJavaVMInitArgs_(vmargs);
83}
84
85jint JniInvocation::JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
86 return JNI_CreateJavaVM_(p_vm, p_env, vm_args);
87}
88
89jint JniInvocation::JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {
90 return JNI_GetCreatedJavaVMs_(vms, size, vm_count);
91}
92
93bool JniInvocation::FindSymbol(void** pointer, const char* symbol) {
94 *pointer = dlsym(handle_, symbol);
95 if (*pointer == NULL) {
96 ALOGE("Failed to find symbol %s: %s\n", symbol, dlerror());
97 dlclose(handle_);
98 handle_ = NULL;
99 return false;
100 }
101 return true;
102}
103
104JniInvocation& JniInvocation::GetJniInvocation() {
105 LOG_ALWAYS_FATAL_IF(jni_invocation_ == NULL,
106 "Failed to create JniInvocation instance before using JNI invocation API");
107 return *jni_invocation_;
108}
109
110extern "C" jint JNI_GetDefaultJavaVMInitArgs(void* vm_args) {
111 return JniInvocation::GetJniInvocation().JNI_GetDefaultJavaVMInitArgs(vm_args);
112}
113
114extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
115 return JniInvocation::GetJniInvocation().JNI_CreateJavaVM(p_vm, p_env, vm_args);
116}
117
118extern "C" jint JNI_GetCreatedJavaVMs(JavaVM** vms, jsize size, jsize* vm_count) {
119 return JniInvocation::GetJniInvocation().JNI_GetCreatedJavaVMs(vms, size, vm_count);
120}