1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
Description:
Fixing the bad JNI code in the font manager code. Two issues:
o The JNIEnv is unique to the thread. It cannot be saved by one thread and
reused by another. Use GetEnv instead.
o The 'font2D' jobject needs to be converted into a global reference because
its lifetime exceeds the lifetime of a native method call.
Evaluation:
Appropriately register/free everything with the garbage collector.
Fix:
# HG changeset patch
# User martin
# Date 1224202830 25200
# Node ID 3c9d6001d8a90698a3540a2a483717f26a98db78
# Parent 68730f05449cd4f39ce1cb82adc6c4e57f87554f
Crash in freetypeScaler.c due to insufficient GC protection
Summary: NewGlobalRef/DeleteGlobalRef as needed.
Reviewed-by:
Contributed-by: yamauchi@google.com
--- openjdk/jdk/make/sun/font/mapfile-vers.openjdk.orig 2009-05-21 13:48:03.000000000 +0000
+++ openjdk/jdk/make/sun/font/mapfile-vers.openjdk 2009-05-26 19:53:17.000000000 +0000
@@ -29,6 +29,7 @@
SUNWprivate_1.1 {
global:
+ JNI_OnLoad;
getSunFontIDs;
newLayoutTableCache;
freeLayoutTableCache;
--- openjdk/jdk/src/share/native/sun/font/freetypeScaler.c.orig 2009-05-21 13:48:03.000000000 +0000
+++ openjdk/jdk/src/share/native/sun/font/freetypeScaler.c 2009-05-26 19:53:17.000000000 +0000
@@ -48,16 +48,6 @@
#define ROUND(x) ((int) (x+0.5))
typedef struct {
- /* Important note:
- JNI forbids sharing same env between different threads.
- We are safe, because pointer is overwritten every time we get into
- JNI call (see setupFTContext).
-
- Pointer is used by font data reading callbacks
- such as ReadTTFontFileFunc.
-
- NB: We may consider switching to JNI_GetEnv. */
- JNIEnv* env;
FT_Library library;
FT_Face face;
jobject font2D;
@@ -90,6 +80,13 @@
void z_error(char *s) {}
#endif
+static JavaVM* jvm = NULL;
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+ jvm = vm;
+ return JNI_VERSION_1_2;
+}
+
/**************** Error handling utilities *****************/
static jmethodID invalidateScalerMID;
@@ -108,6 +105,10 @@
FT_Done_Face(scalerInfo->face);
FT_Done_FreeType(scalerInfo->library);
+ if (scalerInfo->font2D != NULL) {
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
+ }
+
if (scalerInfo->directBuffer != NULL) {
(*env)->DeleteGlobalRef(env, scalerInfo->directBuffer);
}
@@ -131,10 +132,9 @@
#define FILEDATACACHESIZE 1024
-/* NB: is it ever called? */
static void CloseTTFontFileFunc(FT_Stream stream) {
+ JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
FTScalerInfo *scalerInfo = (FTScalerInfo *) stream->pathname.pointer;
- JNIEnv* env = scalerInfo->env;
jclass tmpClass = (*env)->FindClass(env, "sun/font/TrueTypeFont");
jfieldID platNameField =
(*env)->GetFieldID(env, tmpClass, "platName", "Ljava/lang/String;");
@@ -150,8 +150,8 @@
unsigned char* destBuffer,
unsigned long numBytes)
{
+ JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
FTScalerInfo *scalerInfo = (FTScalerInfo *) stream->pathname.pointer;
- JNIEnv* env = scalerInfo->env;
jobject bBuffer;
int bread = 0;
@@ -245,8 +245,7 @@
if (scalerInfo == NULL)
return 0;
- scalerInfo->env = env;
- scalerInfo->font2D = font2D;
+ scalerInfo->font2D = (*env)->NewGlobalRef(env, font2D);
scalerInfo->fontDataOffset = 0;
scalerInfo->fontDataLength = 0;
scalerInfo->fileSize = filesize;
@@ -263,6 +262,7 @@
*/
error = FT_Init_FreeType(&scalerInfo->library);
if (error) {
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
free(scalerInfo);
return 0;
}
@@ -331,6 +331,7 @@
}
if (scalerInfo->fontData != NULL)
free(scalerInfo->fontData);
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
free(scalerInfo);
return 0;
}
@@ -391,8 +392,10 @@
FTScalerContext *context) {
int errCode = 0;
- scalerInfo->env = env;
- scalerInfo->font2D = font2D;
+ if (scalerInfo->font2D != NULL) {
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
+ }
+ scalerInfo->font2D = (*env)->NewGlobalRef(env, font2D);
if (context != NULL) {
FT_Set_Transform(scalerInfo->face, &context->transform, NULL);
|