Skip to content

Commit

Permalink
update demo-c
Browse files Browse the repository at this point in the history
  • Loading branch information
amimo committed Aug 18, 2019
1 parent 6fb6db0 commit e41c6e8
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 39 deletions.
2 changes: 1 addition & 1 deletion tests/demo-c/app/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LOCAL_MODULE := nc
LOCAL_LDLIBS := -llog

SOURCES := $(wildcard $(LOCAL_PATH)/nc/*.cpp)
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/nc
LOCAL_C_INCLUDES := $(LOCAL_PATH)/nc

LOCAL_SRC_FILES := $(SOURCES:$(LOCAL_PATH)/%=%)

Expand Down
4 changes: 3 additions & 1 deletion tests/demo-c/app/src/main/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
APP_STL := c++_static
APP_CPPFLAGS += -fvisibility=hidden
APP_PLATFORM := android-19
APP_ABI := armeabi-v7a arm64-v8a
#APP_ABI := armeabi-v7a arm64-v8a
APP_ABI := armeabi-v7a
130 changes: 98 additions & 32 deletions tests/demo-c/app/src/main/jni/nc/Dex2C.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,48 @@
#include <string.h>
#include <pthread.h>
#include <map>

#include "Dex2C.h"
#include "ScopedLocalRef.h"
#include "ScopedPthreadMutexLock.h"
#include "well_known_classes.h"

struct MemberTriple {
MemberTriple(const char *cls_name, const char *name, const char *sig):class_name_(cls_name), member_name_(name), signautre_(sig) {}
const char *class_name_;
const char *member_name_;
const char *signautre_;

bool operator < (const MemberTriple &member) const {
if (class_name_ != member.class_name_) return class_name_ < member.class_name_;
if (member_name_ != member.member_name_) return member_name_ < member.member_name_;
if (signautre_ != member.signautre_) return signautre_ < member.signautre_;
else return false;
}
};

static std::map<MemberTriple, jfieldID> resvoled_fields;
static std::map<MemberTriple, jmethodID> resvoled_methods;
static std::map<MemberTriple, jclass> resvoled_classes;
static pthread_mutex_t resovle_method_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t resovle_field_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t resovle_class_mutex = PTHREAD_MUTEX_INITIALIZER;

static const int max_global_reference = 1500;

static void cache_well_known_classes(JNIEnv *env) {
d2c::WellKnownClasses::Init(env);

resvoled_classes[MemberTriple("Int", NULL, NULL)] = d2c::WellKnownClasses::primitive_int;
resvoled_classes[MemberTriple("Long", NULL, NULL)] = d2c::WellKnownClasses::primitive_long;
resvoled_classes[MemberTriple("Short", NULL, NULL)] = d2c::WellKnownClasses::primitive_short;
resvoled_classes[MemberTriple("Char", NULL, NULL)] = d2c::WellKnownClasses::primitive_char;
resvoled_classes[MemberTriple("Byte", NULL, NULL)] = d2c::WellKnownClasses::primitive_byte;
resvoled_classes[MemberTriple("Boolean", NULL, NULL)] = d2c::WellKnownClasses::primitive_boolean;
resvoled_classes[MemberTriple("Float", NULL, NULL)] = d2c::WellKnownClasses::primitive_float;
resvoled_classes[MemberTriple("Double", NULL, NULL)] = d2c::WellKnownClasses::primitive_double;
}

void d2c_throw_exception(JNIEnv *env, const char *class_name, const char *message) {
LOGD("d2c_throw_exception %s %s", class_name, message);
ScopedLocalRef<jclass> c(env, env->FindClass(class_name));
Expand Down Expand Up @@ -111,38 +151,32 @@ bool d2c_resolve_class(JNIEnv *env, jclass *cached_class, const char *class_name
return false;
}

if (strcmp(class_name, "Int") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_int;
return false;
} else if (strcmp(class_name, "Long") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_long;
return false;
} else if (strcmp(class_name, "Short") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_short;
return false;
} else if (strcmp(class_name, "Char") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_char;
return false;
} else if (strcmp(class_name, "Byte") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_byte;
return false;
} else if (strcmp(class_name, "Boolean") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_boolean;
return false;
} else if (strcmp(class_name, "Float") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_float;
return false;
} else if (strcmp(class_name, "Double") == 0) {
*cached_class = d2c::WellKnownClasses::primitive_double;
return false;
} else {
jclass clz = env->FindClass(class_name);
if (clz) {
*cached_class = clz;
MemberTriple triple(class_name, NULL, NULL);

if (max_global_reference > 0) {
ScopedPthreadMutexLock lock(&resovle_class_mutex);

auto iter = resvoled_classes.find(triple);
if (iter != resvoled_classes.end()) {
*cached_class = (jclass) iter->second;
return false;
}
}

jclass clz = env->FindClass(class_name);
if (clz) {
LOGD("resvoled class %s %zd", class_name, resvoled_classes.size());
if (max_global_reference > 0 && resvoled_classes.size() < max_global_reference) {
ScopedPthreadMutexLock lock(&resovle_class_mutex);
*cached_class = (jclass) env->NewGlobalRef(clz);
resvoled_classes[triple] = *cached_class;
env->DeleteLocalRef(clz);
} else {
return true;
*cached_class = clz;
}
return false;
} else {
return true;
}
}

Expand All @@ -156,11 +190,28 @@ bool d2c_resolve_method(JNIEnv *env, jclass *cached_class, jmethodID *cached_met
return true;
}

MemberTriple triple(class_name, method_name, signature);
{
ScopedPthreadMutexLock lock(&resovle_method_mutex);

auto iter = resvoled_methods.find(triple);
if (iter != resvoled_methods.end()) {
*cached_method = iter->second;
return false;
}
}

if (is_static) {
*cached_method = env->GetStaticMethodID(*cached_class, method_name, signature);
} else {
*cached_method = env->GetMethodID(*cached_class, method_name, signature);
}

if (*cached_method) {
ScopedPthreadMutexLock lock(&resovle_method_mutex);
resvoled_methods[triple] = *cached_method;
}

return *cached_method == NULL;
}

Expand All @@ -174,22 +225,37 @@ bool d2c_resolve_field(JNIEnv *env, jclass *cached_class, jfieldID *cached_field
return true;
}

MemberTriple triple(class_name, field_name, signature);
{
ScopedPthreadMutexLock lock(&resovle_field_mutex);

auto iter = resvoled_fields.find(triple);
if (iter != resvoled_fields.end()) {
*cached_field = iter->second;
return false;
}
}

if (is_static) {
*cached_field = env->GetStaticFieldID(*cached_class, field_name, signature);
} else {
*cached_field = env->GetFieldID(*cached_class, field_name, signature);
}

if (*cached_field) {
ScopedPthreadMutexLock lock(&resovle_field_mutex);
resvoled_fields[triple] = *cached_field;
}

return *cached_field == NULL;
}


JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env;

if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
return JNI_ERR;
}

d2c::WellKnownClasses::Init(env);
cache_well_known_classes(env);
return JNI_VERSION_1_6;
}
10 changes: 5 additions & 5 deletions tests/demo-c/app/src/main/jni/nc/Dex2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@
//#define DEBUG

#define D2C_RESOLVE_CLASS(cached_class, class_name) \
if (d2c_resolve_class(env, &cached_class, class_name)) { \
if (cached_class == NULL && d2c_resolve_class(env, &cached_class, class_name)) { \
goto EX_HANDLE; \
}

#define D2C_RESOLVE_METHOD(cached_class, cached_method, class_name, method_name, signature) \
if (d2c_resolve_method(env, &cached_class, &cached_method, false, class_name, method_name, signature)) { \
if (cached_method == NULL && d2c_resolve_method(env, &cached_class, &cached_method, false, class_name, method_name, signature)) { \
goto EX_HANDLE; \
}

#define D2C_RESOLVE_STATIC_METHOD(cached_class, cached_method, class_name, method_name, signature) \
if (d2c_resolve_method(env, &cached_class, &cached_method, true, class_name, method_name, signature)) { \
if (cached_method == NULL && d2c_resolve_method(env, &cached_class, &cached_method, true, class_name, method_name, signature)) { \
goto EX_HANDLE; \
}

#define D2C_RESOLVE_FIELD(cached_class, cached_field, class_name, field_name, signature) \
if (d2c_resolve_field(env, &cached_class, &cached_field, false, class_name, field_name, signature)) { \
if (cached_field == NULL && d2c_resolve_field(env, &cached_class, &cached_field, false, class_name, field_name, signature)) { \
goto EX_HANDLE; \
}

#define D2C_RESOLVE_STATIC_FIELD(cached_class, cached_field, class_name, field_name, signature) \
if (d2c_resolve_field(env, &cached_class, &cached_field, true, class_name, field_name, signature)) { \
if (cached_field == NULL && d2c_resolve_field(env, &cached_class, &cached_field, true, class_name, field_name, signature)) { \
goto EX_HANDLE; \
}

Expand Down
43 changes: 43 additions & 0 deletions tests/demo-c/app/src/main/jni/nc/ScopedPthreadMutexLock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2010 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.
*/

#ifndef SCOPED_PTHREAD_MUTEX_LOCK_H_included
#define SCOPED_PTHREAD_MUTEX_LOCK_H_included

#include <pthread.h>

/**
* Locks and unlocks a pthread_mutex_t as it goes in and out of scope.
*/
class ScopedPthreadMutexLock {
public:
explicit ScopedPthreadMutexLock(pthread_mutex_t* mutex) : mMutexPtr(mutex) {
pthread_mutex_lock(mMutexPtr);
}

~ScopedPthreadMutexLock() {
pthread_mutex_unlock(mMutexPtr);
}

private:
pthread_mutex_t* mMutexPtr;

// Disallow copy and assignment.
ScopedPthreadMutexLock(const ScopedPthreadMutexLock&);
void operator=(const ScopedPthreadMutexLock&);
};

#endif // SCOPED_PTHREAD_MUTEX_LOCK_H_included

0 comments on commit e41c6e8

Please sign in to comment.