|
16 | 16 | * limitations under the License. |
17 | 17 | */ |
18 | 18 |
|
| 19 | +#include "exception.h" |
19 | 20 | #include "jclasses.h" |
20 | 21 | #include "jni_helper.h" |
21 | | -#include "exception.h" |
| 22 | +#include "os/mutexes.h" |
22 | 23 |
|
23 | 24 | #include <assert.h> |
24 | 25 |
|
25 | | -int jclassesInitialized = 0; |
| 26 | +/** |
| 27 | + * Whether initCachedClasses has been called or not. Protected by the mutex |
| 28 | + * jclassInitMutex. |
| 29 | + */ |
| 30 | +static int jclassesInitialized = 0; |
26 | 31 |
|
27 | | -struct javaClassAndName { |
| 32 | +typedef struct { |
28 | 33 | jclass javaClass; |
29 | 34 | const char *className; |
30 | | -}; |
| 35 | +} javaClassAndName; |
31 | 36 |
|
32 | 37 | /** |
33 | 38 | * A collection of commonly used jclass objects that are used throughout |
34 | 39 | * libhdfs. The jclasses are loaded immediately after the JVM is created (see |
35 | 40 | * initCachedClasses). The array is indexed using CachedJavaClass. |
36 | 41 | */ |
37 | | -struct javaClassAndName cachedJavaClasses[NUM_CACHED_CLASSES]; |
| 42 | +javaClassAndName cachedJavaClasses[NUM_CACHED_CLASSES]; |
38 | 43 |
|
39 | 44 | /** |
40 | 45 | * Helper method that creates and sets a jclass object given a class name. |
@@ -62,57 +67,63 @@ static jthrowable initCachedClass(JNIEnv *env, const char *className, |
62 | 67 | } |
63 | 68 |
|
64 | 69 | jthrowable initCachedClasses(JNIEnv* env) { |
65 | | - // Set all the class names |
66 | | - cachedJavaClasses[JC_CONFIGURATION].className = |
67 | | - "org/apache/hadoop/conf/Configuration"; |
68 | | - cachedJavaClasses[JC_PATH].className = |
69 | | - "org/apache/hadoop/fs/Path"; |
70 | | - cachedJavaClasses[JC_FILE_SYSTEM].className = |
71 | | - "org/apache/hadoop/fs/FileSystem"; |
72 | | - cachedJavaClasses[JC_FS_STATUS].className = |
73 | | - "org/apache/hadoop/fs/FsStatus"; |
74 | | - cachedJavaClasses[JC_FILE_UTIL].className = |
75 | | - "org/apache/hadoop/fs/FileUtil"; |
76 | | - cachedJavaClasses[JC_BLOCK_LOCATION].className = |
77 | | - "org/apache/hadoop/fs/BlockLocation"; |
78 | | - cachedJavaClasses[JC_DFS_HEDGED_READ_METRICS].className = |
79 | | - "org/apache/hadoop/hdfs/DFSHedgedReadMetrics"; |
80 | | - cachedJavaClasses[JC_DISTRIBUTED_FILE_SYSTEM].className = |
81 | | - "org/apache/hadoop/hdfs/DistributedFileSystem"; |
82 | | - cachedJavaClasses[JC_FS_DATA_INPUT_STREAM].className = |
83 | | - "org/apache/hadoop/fs/FSDataInputStream"; |
84 | | - cachedJavaClasses[JC_FS_DATA_OUTPUT_STREAM].className = |
85 | | - "org/apache/hadoop/fs/FSDataOutputStream"; |
86 | | - cachedJavaClasses[JC_FILE_STATUS].className = |
87 | | - "org/apache/hadoop/fs/FileStatus"; |
88 | | - cachedJavaClasses[JC_FS_PERMISSION].className = |
89 | | - "org/apache/hadoop/fs/permission/FsPermission"; |
90 | | - cachedJavaClasses[JC_READ_STATISTICS].className = |
91 | | - "org/apache/hadoop/hdfs/ReadStatistics"; |
92 | | - cachedJavaClasses[JC_HDFS_DATA_INPUT_STREAM].className = |
93 | | - "org/apache/hadoop/hdfs/client/HdfsDataInputStream"; |
94 | | - cachedJavaClasses[JC_DOMAIN_SOCKET].className = |
95 | | - "org/apache/hadoop/net/unix/DomainSocket"; |
96 | | - cachedJavaClasses[JC_URI].className = |
97 | | - "java/net/URI"; |
98 | | - cachedJavaClasses[JC_BYTE_BUFFER].className = |
99 | | - "java/nio/ByteBuffer"; |
100 | | - cachedJavaClasses[JC_ENUM_SET].className = |
101 | | - "java/util/EnumSet"; |
102 | | - cachedJavaClasses[JC_EXCEPTION_UTILS].className = |
103 | | - "org/apache/commons/lang3/exception/ExceptionUtils"; |
| 70 | + mutexLock(&jclassInitMutex); |
| 71 | + if (!jclassesInitialized) { |
| 72 | + // Set all the class names |
| 73 | + cachedJavaClasses[JC_CONFIGURATION].className = |
| 74 | + "org/apache/hadoop/conf/Configuration"; |
| 75 | + cachedJavaClasses[JC_PATH].className = |
| 76 | + "org/apache/hadoop/fs/Path"; |
| 77 | + cachedJavaClasses[JC_FILE_SYSTEM].className = |
| 78 | + "org/apache/hadoop/fs/FileSystem"; |
| 79 | + cachedJavaClasses[JC_FS_STATUS].className = |
| 80 | + "org/apache/hadoop/fs/FsStatus"; |
| 81 | + cachedJavaClasses[JC_FILE_UTIL].className = |
| 82 | + "org/apache/hadoop/fs/FileUtil"; |
| 83 | + cachedJavaClasses[JC_BLOCK_LOCATION].className = |
| 84 | + "org/apache/hadoop/fs/BlockLocation"; |
| 85 | + cachedJavaClasses[JC_DFS_HEDGED_READ_METRICS].className = |
| 86 | + "org/apache/hadoop/hdfs/DFSHedgedReadMetrics"; |
| 87 | + cachedJavaClasses[JC_DISTRIBUTED_FILE_SYSTEM].className = |
| 88 | + "org/apache/hadoop/hdfs/DistributedFileSystem"; |
| 89 | + cachedJavaClasses[JC_FS_DATA_INPUT_STREAM].className = |
| 90 | + "org/apache/hadoop/fs/FSDataInputStream"; |
| 91 | + cachedJavaClasses[JC_FS_DATA_OUTPUT_STREAM].className = |
| 92 | + "org/apache/hadoop/fs/FSDataOutputStream"; |
| 93 | + cachedJavaClasses[JC_FILE_STATUS].className = |
| 94 | + "org/apache/hadoop/fs/FileStatus"; |
| 95 | + cachedJavaClasses[JC_FS_PERMISSION].className = |
| 96 | + "org/apache/hadoop/fs/permission/FsPermission"; |
| 97 | + cachedJavaClasses[JC_READ_STATISTICS].className = |
| 98 | + "org/apache/hadoop/hdfs/ReadStatistics"; |
| 99 | + cachedJavaClasses[JC_HDFS_DATA_INPUT_STREAM].className = |
| 100 | + "org/apache/hadoop/hdfs/client/HdfsDataInputStream"; |
| 101 | + cachedJavaClasses[JC_DOMAIN_SOCKET].className = |
| 102 | + "org/apache/hadoop/net/unix/DomainSocket"; |
| 103 | + cachedJavaClasses[JC_URI].className = |
| 104 | + "java/net/URI"; |
| 105 | + cachedJavaClasses[JC_BYTE_BUFFER].className = |
| 106 | + "java/nio/ByteBuffer"; |
| 107 | + cachedJavaClasses[JC_ENUM_SET].className = |
| 108 | + "java/util/EnumSet"; |
| 109 | + cachedJavaClasses[JC_EXCEPTION_UTILS].className = |
| 110 | + "org/apache/commons/lang3/exception/ExceptionUtils"; |
104 | 111 |
|
105 | | - // Create and set the jclass objects based on the class names set above |
106 | | - jthrowable jthr; |
107 | | - int numCachedClasses = |
108 | | - sizeof(cachedJavaClasses) / sizeof(struct javaClassAndName); |
109 | | - for (int i = 0; i < numCachedClasses; i++) { |
110 | | - jthr = initCachedClass(env, cachedJavaClasses[i].className, |
111 | | - &cachedJavaClasses[i].javaClass); |
112 | | - if (jthr) { |
113 | | - return jthr; |
| 112 | + // Create and set the jclass objects based on the class names set above |
| 113 | + jthrowable jthr; |
| 114 | + int numCachedClasses = |
| 115 | + sizeof(cachedJavaClasses) / sizeof(javaClassAndName); |
| 116 | + for (int i = 0; i < numCachedClasses; i++) { |
| 117 | + jthr = initCachedClass(env, cachedJavaClasses[i].className, |
| 118 | + &cachedJavaClasses[i].javaClass); |
| 119 | + if (jthr) { |
| 120 | + mutexUnlock(&jclassInitMutex); |
| 121 | + return jthr; |
| 122 | + } |
114 | 123 | } |
| 124 | + jclassesInitialized = 1; |
115 | 125 | } |
| 126 | + mutexUnlock(&jclassInitMutex); |
116 | 127 | return NULL; |
117 | 128 | } |
118 | 129 |
|
|
0 commit comments