Skip to content

Commit 2579c9a

Browse files
janakdrcopybara-github
authored andcommitted
Eagerly initialize JNI copies of Java classes: doing lazy initialization on a per-method basis doesn't save anything and adds a tiny bit of overhead to every one of these calls.
PiperOrigin-RevId: 380833502
1 parent 2640745 commit 2579c9a

File tree

2 files changed

+77
-74
lines changed

2 files changed

+77
-74
lines changed

src/main/java/com/google/devtools/build/lib/unix/NativePosixFiles.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,29 +27,28 @@
2727
* by the java.io package where appropriate--see package javadoc for details.
2828
*/
2929
public final class NativePosixFiles {
30-
3130
private NativePosixFiles() {}
3231

3332
static {
3433
if (!java.nio.charset.Charset.defaultCharset().name().equals("ISO-8859-1")) {
3534
// Defer the Logger call, so we don't deadlock if this is called from Logger
3635
// initialization code.
37-
new Thread() {
38-
@Override
39-
public void run() {
40-
// wait (if necessary) until the logging system is initialized
41-
synchronized (LogManager.getLogManager()) {
42-
}
43-
GoogleLogger.forEnclosingClass()
44-
.atFine()
45-
.log(
46-
"WARNING: Default character set is not latin1; java.io.File and "
47-
+ "com.google.devtools.build.lib.unix.FilesystemUtils will represent some "
48-
+ "filenames differently.");
49-
}
50-
}.start();
36+
new Thread(
37+
() -> {
38+
// wait (if necessary) until the logging system is initialized
39+
synchronized (LogManager.getLogManager()) {
40+
}
41+
@SuppressWarnings("FloggerRequiredModifiers")
42+
GoogleLogger logger = GoogleLogger.forEnclosingClass();
43+
logger.atFine().log(
44+
"WARNING: Default character set is not latin1; java.io.File and"
45+
+ " com.google.devtools.build.lib.unix.FilesystemUtils will represent"
46+
+ " some filenames differently.");
47+
})
48+
.start();
5149
}
5250
JniLoader.loadJni();
51+
initJNIClasses();
5352
}
5453

5554
/**
@@ -375,4 +374,6 @@ public static native byte[] lgetxattr(String path, String name)
375374
* reference alive.
376375
*/
377376
public static native int close(int fd, Object ignored) throws IOException;
377+
378+
private static native void initJNIClasses();
378379
}

src/main/native/unix_jni.cc

Lines changed: 61 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -217,63 +217,52 @@ Java_com_google_devtools_build_lib_unix_NativePosixFiles_symlink(JNIEnv *env,
217217
link_common(env, oldpath, newpath, ::symlink);
218218
}
219219

220-
static jobject NewFileStatus(JNIEnv *env,
221-
const portable_stat_struct &stat_ref) {
222-
static jclass file_status_class = nullptr;
223-
if (file_status_class == nullptr) { // note: harmless race condition
224-
jclass local =
225-
env->FindClass("com/google/devtools/build/lib/unix/FileStatus");
226-
CHECK(local != nullptr);
227-
file_status_class = static_cast<jclass>(env->NewGlobalRef(local));
228-
}
220+
namespace {
221+
static jclass file_status_class = nullptr;
222+
static jclass errno_file_status_class = nullptr;
223+
static jmethodID file_status_class_ctor = nullptr;
224+
static jmethodID errno_file_status_class_no_error_ctor = nullptr;
225+
static jmethodID errno_file_status_class_errorno_ctor = nullptr;
226+
static jclass dirents_class = nullptr;
227+
static jmethodID dirents_ctor = nullptr;
228+
229+
static jclass makeStaticClass(JNIEnv *env, const char *name) {
230+
jclass lookup_result = env->FindClass(name);
231+
CHECK(lookup_result != nullptr);
232+
return static_cast<jclass>(env->NewGlobalRef(lookup_result));
233+
}
229234

230-
static jmethodID method = nullptr;
231-
if (method == nullptr) { // note: harmless race condition
232-
method = env->GetMethodID(file_status_class, "<init>", "(IIIIIIIJIJ)V");
233-
CHECK(method != nullptr);
234-
}
235+
static jmethodID getConstructorID(JNIEnv *env, jclass clazz,
236+
const char *parameters) {
237+
jmethodID method = env->GetMethodID(clazz, "<init>", parameters);
238+
CHECK(method != nullptr);
239+
return method;
240+
}
235241

242+
static jobject NewFileStatus(JNIEnv *env,
243+
const portable_stat_struct &stat_ref) {
236244
return env->NewObject(
237-
file_status_class, method, stat_ref.st_mode,
245+
file_status_class, file_status_class_ctor, stat_ref.st_mode,
238246
StatSeconds(stat_ref, STAT_ATIME), StatNanoSeconds(stat_ref, STAT_ATIME),
239247
StatSeconds(stat_ref, STAT_MTIME), StatNanoSeconds(stat_ref, STAT_MTIME),
240248
StatSeconds(stat_ref, STAT_CTIME), StatNanoSeconds(stat_ref, STAT_CTIME),
241-
static_cast<jlong>(stat_ref.st_size),
242-
static_cast<int>(stat_ref.st_dev), static_cast<jlong>(stat_ref.st_ino));
249+
static_cast<jlong>(stat_ref.st_size), static_cast<int>(stat_ref.st_dev),
250+
static_cast<jlong>(stat_ref.st_ino));
243251
}
244252

245253
static jobject NewErrnoFileStatus(JNIEnv *env,
246254
int saved_errno,
247255
const portable_stat_struct &stat_ref) {
248-
static jclass errno_file_status_class = nullptr;
249-
if (errno_file_status_class == nullptr) { // note: harmless race condition
250-
jclass local =
251-
env->FindClass("com/google/devtools/build/lib/unix/ErrnoFileStatus");
252-
CHECK(local != nullptr);
253-
errno_file_status_class = static_cast<jclass>(env->NewGlobalRef(local));
254-
}
255-
256-
static jmethodID no_error_ctor = nullptr;
257-
if (no_error_ctor == nullptr) { // note: harmless race condition
258-
no_error_ctor = env->GetMethodID(errno_file_status_class,
259-
"<init>", "(IIIIIIIJIJ)V");
260-
CHECK(no_error_ctor != nullptr);
261-
}
262-
263-
static jmethodID errorno_ctor = nullptr;
264-
if (errorno_ctor == nullptr) { // note: harmless race condition
265-
errorno_ctor = env->GetMethodID(errno_file_status_class, "<init>", "(I)V");
266-
CHECK(errorno_ctor != nullptr);
267-
}
268-
269256
if (saved_errno != 0) {
270-
return env->NewObject(errno_file_status_class, errorno_ctor, saved_errno);
257+
return env->NewObject(errno_file_status_class,
258+
errno_file_status_class_errorno_ctor, saved_errno);
271259
}
272260
return env->NewObject(
273-
errno_file_status_class, no_error_ctor, stat_ref.st_mode,
274-
StatSeconds(stat_ref, STAT_ATIME), StatNanoSeconds(stat_ref, STAT_ATIME),
275-
StatSeconds(stat_ref, STAT_MTIME), StatNanoSeconds(stat_ref, STAT_MTIME),
276-
StatSeconds(stat_ref, STAT_CTIME), StatNanoSeconds(stat_ref, STAT_CTIME),
261+
errno_file_status_class, errno_file_status_class_no_error_ctor,
262+
stat_ref.st_mode, StatSeconds(stat_ref, STAT_ATIME),
263+
StatNanoSeconds(stat_ref, STAT_ATIME), StatSeconds(stat_ref, STAT_MTIME),
264+
StatNanoSeconds(stat_ref, STAT_MTIME), StatSeconds(stat_ref, STAT_CTIME),
265+
StatNanoSeconds(stat_ref, STAT_CTIME),
277266
static_cast<jlong>(stat_ref.st_size), static_cast<int>(stat_ref.st_dev),
278267
static_cast<jlong>(stat_ref.st_ino));
279268
}
@@ -287,6 +276,26 @@ static void SetIntField(JNIEnv *env,
287276
CHECK(fid != nullptr);
288277
env->SetIntField(object, fid, val);
289278
}
279+
} // namespace
280+
281+
extern "C" JNIEXPORT void JNICALL
282+
Java_com_google_devtools_build_lib_unix_NativePosixFiles_initJNIClasses(
283+
JNIEnv *env, jclass clazz) {
284+
file_status_class =
285+
makeStaticClass(env, "com/google/devtools/build/lib/unix/FileStatus");
286+
errno_file_status_class = makeStaticClass(
287+
env, "com/google/devtools/build/lib/unix/ErrnoFileStatus");
288+
file_status_class_ctor =
289+
getConstructorID(env, file_status_class, "(IIIIIIIJIJ)V");
290+
errno_file_status_class_no_error_ctor =
291+
getConstructorID(env, errno_file_status_class, "(IIIIIIIJIJ)V");
292+
errno_file_status_class_errorno_ctor =
293+
getConstructorID(env, errno_file_status_class, "(I)V");
294+
dirents_class = makeStaticClass(
295+
env, "com/google/devtools/build/lib/unix/NativePosixFiles$Dirents");
296+
dirents_ctor =
297+
getConstructorID(env, dirents_class, "([Ljava/lang/String;[B)V");
298+
}
290299

291300
extern "C" JNIEXPORT void JNICALL
292301
Java_com_google_devtools_build_lib_unix_ErrnoFileStatus_00024ErrnoConstants_initErrnoConstants( // NOLINT
@@ -299,6 +308,7 @@ Java_com_google_devtools_build_lib_unix_ErrnoFileStatus_00024ErrnoConstants_init
299308
SetIntField(env, clazz, errno_constants, "ENAMETOOLONG", ENAMETOOLONG);
300309
}
301310

311+
namespace {
302312
static jobject StatCommon(JNIEnv *env, jstring path,
303313
int (*stat_function)(const char *,
304314
portable_stat_struct *),
@@ -331,6 +341,7 @@ static jobject StatCommon(JNIEnv *env, jstring path,
331341
? NewFileStatus(env, statbuf)
332342
: NewErrnoFileStatus(env, saved_errno, statbuf);
333343
}
344+
} // namespace
334345

335346
/*
336347
* Class: com.google.devtools.build.lib.unix.NativePosixFiles
@@ -536,25 +547,11 @@ Java_com_google_devtools_build_lib_unix_NativePosixFiles_mkdirs(JNIEnv *env,
536547
ReleaseStringLatin1Chars(path_chars);
537548
}
538549

550+
namespace {
539551
static jobject NewDirents(JNIEnv *env,
540552
jobjectArray names,
541553
jbyteArray types) {
542-
// See http://java.sun.com/docs/books/jni/html/fldmeth.html#26855
543-
static jclass dirents_class = nullptr;
544-
if (dirents_class == nullptr) { // note: harmless race condition
545-
jclass local = env->FindClass("com/google/devtools/build/lib/unix/NativePosixFiles$Dirents");
546-
CHECK(local != nullptr);
547-
dirents_class = static_cast<jclass>(env->NewGlobalRef(local));
548-
}
549-
550-
static jmethodID ctor = nullptr;
551-
if (ctor == nullptr) { // note: harmless race condition
552-
ctor =
553-
env->GetMethodID(dirents_class, "<init>", "([Ljava/lang/String;[B)V");
554-
CHECK(ctor != nullptr);
555-
}
556-
557-
return env->NewObject(dirents_class, ctor, names, types);
554+
return env->NewObject(dirents_class, dirents_ctor, names, types);
558555
}
559556

560557
static char GetDirentType(struct dirent *entry,
@@ -582,6 +579,7 @@ static char GetDirentType(struct dirent *entry,
582579
return '?';
583580
}
584581
}
582+
} // namespace
585583

586584
/*
587585
* Class: com.google.devtools.build.lib.unix.NativePosixFiles
@@ -739,6 +737,7 @@ Java_com_google_devtools_build_lib_unix_NativePosixFiles_mkfifo(JNIEnv *env,
739737
ReleaseStringLatin1Chars(path_chars);
740738
}
741739

740+
namespace {
742741
// Posts an exception generated by the DeleteTreesBelow algorithm and its helper
743742
// functions.
744743
//
@@ -973,6 +972,7 @@ static int DeleteTreesBelow(JNIEnv* env, std::vector<std::string>* dir_path,
973972
dir_path->pop_back();
974973
return env->ExceptionOccurred() == nullptr ? 0 : -1;
975974
}
975+
} // namespace
976976

977977
/*
978978
* Class: com.google.devtools.build.lib.unix.NativePosixFiles
@@ -995,6 +995,7 @@ Java_com_google_devtools_build_lib_unix_NativePosixFiles_deleteTreesBelow(
995995
////////////////////////////////////////////////////////////////////////
996996
// Linux extended file attributes
997997

998+
namespace {
998999
typedef ssize_t getxattr_func(const char *path, const char *name,
9991000
void *value, size_t size, bool *attr_not_found);
10001001

@@ -1027,6 +1028,7 @@ static jbyteArray getxattr_common(JNIEnv *env,
10271028
ReleaseStringLatin1Chars(name_chars);
10281029
return result;
10291030
}
1031+
} // namespace
10301032

10311033
extern "C" JNIEXPORT jbyteArray JNICALL
10321034
Java_com_google_devtools_build_lib_unix_NativePosixFiles_getxattr(JNIEnv *env,

0 commit comments

Comments
 (0)