Skip to content
This repository was archived by the owner on Mar 25, 2019. It is now read-only.

Commit 519f8b2

Browse files
author
ericwlange
committed
Fixed all known memory leaks and instabilities
Separated out Instance and JSFunction implementation in C++ for better readability Updated copyright notices Added test for memory leakage
1 parent 03060c7 commit 519f8b2

29 files changed

Lines changed: 1019 additions & 584 deletions

AndroidJSCore/AndroidJSCore/jni/Android.mk

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
#
2+
# Android.mk
3+
# AndroidJSCore project
4+
#
5+
# https://github.com/ericwlange/AndroidJSCore/
6+
#
7+
# Created by Eric Lange
8+
#
9+
#
10+
# Copyright (c) 2014-2016 Eric Lange. All rights reserved.
11+
#
12+
# Redistribution and use in source and binary forms, with or without
13+
# modification, are permitted provided that the following conditions are met:
14+
#
15+
# - Redistributions of source code must retain the above copyright notice, this
16+
# list of conditions and the following disclaimer.
17+
#
18+
# - Redistributions in binary form must reproduce the above copyright notice,
19+
# this list of conditions and the following disclaimer in the documentation
20+
# and/or other materials provided with the distribution.
21+
#
22+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
133
LOCAL_PATH := $(call my-dir)
234

335
include $(CLEAR_VARS)
@@ -6,7 +38,9 @@ LOCAL_MODULE := android-js-core
638
LOCAL_SRC_FILES := JSContext.cpp \
739
JSObject.cpp \
840
JSString.cpp \
9-
JSValue.cpp
41+
JSValue.cpp \
42+
Instance.cpp \
43+
JSFunction.cpp
1044

1145
HEMROID_MODULES := javascriptcore_$(TARGET_ARCH_ABI) icustub_$(TARGET_ARCH_ABI)
1246
LOCAL_SHARED_LIBRARIES := $(HEMROID_MODULES)

AndroidJSCore/AndroidJSCore/jni/Application.mk

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
#
2+
# Application.mk
3+
# AndroidJSCore project
4+
#
5+
# https://github.com/ericwlange/AndroidJSCore/
6+
#
7+
# Created by Eric Lange
8+
#
9+
#
10+
# Copyright (c) 2014-2016 Eric Lange. All rights reserved.
11+
#
12+
# Redistribution and use in source and binary forms, with or without
13+
# modification, are permitted provided that the following conditions are met:
14+
#
15+
# - Redistributions of source code must retain the above copyright notice, this
16+
# list of conditions and the following disclaimer.
17+
#
18+
# - Redistributions in binary form must reproduce the above copyright notice,
19+
# this list of conditions and the following disclaimer in the documentation
20+
# and/or other materials provided with the distribution.
21+
#
22+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
133
APP_ABI := all
234
APP_PLATFORM := android-9
335
APP_STL := gnustl_shared
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//
2+
// Instance.cpp
3+
// AndroidJSCore project
4+
//
5+
// https://github.com/ericwlange/AndroidJSCore/
6+
//
7+
// Created by Eric Lange
8+
//
9+
/*
10+
Copyright (c) 2014-2016 Eric Lange. All rights reserved.
11+
12+
Redistribution and use in source and binary forms, with or without
13+
modification, are permitted provided that the following conditions are met:
14+
15+
- Redistributions of source code must retain the above copyright notice, this
16+
list of conditions and the following disclaimer.
17+
18+
- Redistributions in binary form must reproduce the above copyright notice,
19+
this list of conditions and the following disclaimer in the documentation
20+
and/or other materials provided with the distribution.
21+
22+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*/
33+
34+
#include "Instance.h"
35+
36+
Instance::Instance(JNIEnv *env, jobject thiz, JSContextRef ctx,
37+
JSClassDefinition def, JSStringRef name)
38+
{
39+
env->GetJavaVM(&jvm);
40+
definition = def;
41+
definition.finalize = StaticFinalizeCallback;
42+
classRef = JSClassCreate(&definition);
43+
objRef = JSObjectMake(ctx, classRef, name);
44+
JSValueProtect(ctx, objRef);
45+
this->thiz = env->NewWeakGlobalRef(thiz);
46+
47+
mutex.lock();
48+
objMap[objRef] = this;
49+
mutex.unlock();
50+
}
51+
52+
Instance::~Instance()
53+
{
54+
JSClassRelease(classRef);
55+
JNIEnv *env;
56+
int getEnvStat = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
57+
if (getEnvStat == JNI_EDETACHED) {
58+
jvm->AttachCurrentThread(&env, NULL);
59+
}
60+
env->DeleteWeakGlobalRef(thiz);
61+
62+
mutex.lock();
63+
objMap.erase(objRef);
64+
mutex.unlock();
65+
66+
if (getEnvStat == JNI_EDETACHED) {
67+
jvm->DetachCurrentThread();
68+
}
69+
}
70+
71+
Instance* Instance::getInstance(JSObjectRef objref)
72+
{
73+
Instance *inst = NULL;
74+
mutex.lock();
75+
inst = objMap[objref];
76+
mutex.unlock();
77+
return inst;
78+
}
79+
80+
std::map<JSObjectRef,Instance *> Instance::objMap = std::map<JSObjectRef,Instance *>();
81+
std::mutex Instance::mutex;
82+
83+
void Instance::StaticFinalizeCallback(JSObjectRef object)
84+
{
85+
Instance *thiz = getInstance(object);
86+
87+
if (thiz) {
88+
delete thiz;
89+
}
90+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// Instance.h
3+
// AndroidJSCore project
4+
//
5+
// https://github.com/ericwlange/AndroidJSCore/
6+
//
7+
// Created by Eric Lange
8+
//
9+
/*
10+
Copyright (c) 2014-2016 Eric Lange. All rights reserved.
11+
12+
Redistribution and use in source and binary forms, with or without
13+
modification, are permitted provided that the following conditions are met:
14+
15+
- Redistributions of source code must retain the above copyright notice, this
16+
list of conditions and the following disclaimer.
17+
18+
- Redistributions in binary form must reproduce the above copyright notice,
19+
this list of conditions and the following disclaimer in the documentation
20+
and/or other materials provided with the distribution.
21+
22+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*/
33+
34+
#ifndef ANDROIDJSCORE_INSTANCE_H
35+
#define ANDROIDJSCORE_INSTANCE_H
36+
37+
#include "JSJNI.h"
38+
#include <map>
39+
#include <mutex>
40+
41+
class Instance {
42+
public:
43+
Instance(JNIEnv *env, jobject thiz, JSContextRef ctx,
44+
JSClassDefinition def = kJSClassDefinitionEmpty, JSStringRef name = NULL);
45+
virtual ~Instance();
46+
virtual long getObjRef() { return (long) objRef; }
47+
static Instance* getInstance(JSObjectRef objref);
48+
49+
protected:
50+
JavaVM *jvm;
51+
jobject thiz;
52+
53+
private:
54+
JSObjectRef objRef;
55+
JSClassRef classRef;
56+
JSClassDefinition definition;
57+
58+
static std::map<JSObjectRef,Instance *> objMap;
59+
static std::mutex mutex;
60+
61+
static void StaticFinalizeCallback(JSObjectRef object);
62+
};
63+
64+
#endif //ANDROIDJSCORE_INSTANCE_H

AndroidJSCore/AndroidJSCore/jni/JSContext.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ NATIVE(JSContext,void,staticInit) (PARAMS) {
6969
}
7070

7171
NATIVE(JSContextGroup,jlong,create) (PARAMS) {
72-
return (long) JSContextGroupCreate();
72+
JSContextGroupRef group = JSContextGroupCreate();
73+
JSContextGroupRetain(group);
74+
return (long)group;
7375
}
7476

7577
NATIVE(JSContextGroup,jlong,retain) (PARAMS,jlong group) {
@@ -80,17 +82,17 @@ NATIVE(JSContextGroup,void,release) (PARAMS,jlong group) {
8082
JSContextGroupRelease((JSContextGroupRef) group);
8183
}
8284

83-
NATIVE(JSContext,void,finalizeContext) (PARAMS,jlong ctx) {
84-
// Nothing to do
85-
}
86-
8785
NATIVE(JSContext,jlong,create) (PARAMS) {
88-
return (jlong) JSGlobalContextCreate((JSClassRef) NULL);
86+
JSGlobalContextRef ref = JSGlobalContextCreate((JSClassRef) NULL);
87+
//JSGlobalContextRetain(ref);
88+
return (long)ref;
8989
}
9090

9191
NATIVE(JSContext,jlong,createInGroup) (PARAMS,jlong group) {
92-
return (jlong) JSGlobalContextCreateInGroup((JSContextGroupRef)group,
92+
JSGlobalContextRef ref = JSGlobalContextCreateInGroup((JSContextGroupRef)group,
9393
(JSClassRef) NULL);
94+
//JSGlobalContextRetain(ref);
95+
return (long)ref;
9496
}
9597

9698
NATIVE(JSContext,jlong,retain) (PARAMS,jlong ctx) {
@@ -102,11 +104,15 @@ NATIVE(JSContext,void,release) (PARAMS,jlong ctx) {
102104
}
103105

104106
NATIVE(JSContext,jlong,getGlobalObject) (PARAMS, jlong ctx) {
105-
return (jlong) JSContextGetGlobalObject((JSContextRef) ctx);
107+
JSObjectRef ref = JSContextGetGlobalObject((JSContextRef) ctx);
108+
JSValueProtect((JSContextRef)ctx,ref);
109+
return (long)ref;
106110
}
107111

108112
NATIVE(JSContext,jlong,getGroup) (PARAMS, jlong ctx) {
109-
return (jlong)JSContextGetGroup((JSContextRef) ctx);
113+
JSContextGroupRef group = JSContextGetGroup((JSContextRef) ctx);
114+
JSContextGroupRetain(group);
115+
return (long)group;
110116
}
111117

112118
NATIVE(JSContext,jobject,evaluateScript) (PARAMS, jlong ctx, jlong script,
@@ -120,19 +126,22 @@ NATIVE(JSContext,jobject,evaluateScript) (PARAMS, jlong ctx, jlong script,
120126

121127
jfieldID fid = env->GetFieldID(ret , "reference", "J");
122128

123-
jlong lval = (jlong) JSEvaluateScript(
129+
JSValueRef value = JSEvaluateScript(
124130
(JSContextRef)ctx,
125131
(JSStringRef)script,
126132
(JSObjectRef)thisObject,
127133
(JSStringRef)sourceURL,
128134
startingLineNumber,
129135
&exception);
136+
JSValueProtect((JSContextRef)ctx, value);
130137

131-
env->SetLongField( out, fid, lval);
138+
env->SetLongField( out, fid, (long)value);
132139

133140
fid = env->GetFieldID(ret , "exception", "J");
134141
env->SetLongField( out, fid, (jlong) exception);
135142

143+
env->DeleteLocalRef(ret);
144+
136145
return out;
137146
}
138147

@@ -146,17 +155,19 @@ NATIVE(JSContext,jobject,checkScriptSyntax) (PARAMS, jlong ctx, jlong script,
146155
jobject out = env->NewObject(ret, cid);
147156

148157
jfieldID fid = env->GetFieldID(ret , "reference", "J");
149-
jlong lval = (jlong) JSCheckScriptSyntax(
158+
bool value = JSCheckScriptSyntax(
150159
(JSContextRef)ctx,
151160
(JSStringRef)script,
152161
(JSStringRef)sourceURL,
153162
startingLineNumber,
154163
&exception);
155-
env->SetLongField( out, fid, (jlong) lval );
164+
env->SetBooleanField( out, fid, value );
156165

157166
fid = env->GetFieldID(ret , "exception", "J");
158167
env->SetLongField( out, fid, (jlong) exception);
159168

169+
env->DeleteLocalRef(ret);
170+
160171
return out;
161172
}
162173

0 commit comments

Comments
 (0)