Skip to content

Commit 2949efb

Browse files
authored
Merge pull request #280 from rpavlik/update-jni-wrappers
Update jni wrappers, jnipp
2 parents a45755e + 5a3e055 commit 2949efb

File tree

7 files changed

+123
-4
lines changed

7 files changed

+123
-4
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Update jnipp to fix crash on Android if app detatches thread from JVM (e.g. on shutdown).
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
- issue.275.gh.OpenXR-SDK-Source
3+
- issue.1616.gl
4+
---
5+
- Update android-jni-wrappers to fix missing include.

src/external/android-jni-wrappers/wrap/ObjectWrapperBase.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// Copyright 2020, Collabora, Ltd.
1+
// Copyright 2020-2021, Collabora, Ltd.
22
// SPDX-License-Identifier: BSL-1.0
33
// Author: Ryan Pavlik <[email protected]>
44

55
#pragma once
6+
#include <assert.h>
67
#include <jni.h>
78
#include <jnipp.h>
89

src/external/jnipp/jnipp.cpp

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#else
77
// UNIX Dependencies
88
# include <dlfcn.h>
9+
# include <unistd.h>
10+
# include <tuple>
911
#endif
1012

1113
// External Dependencies
@@ -24,6 +26,10 @@ namespace jni
2426
static std::atomic_bool isVm(false);
2527
static JavaVM* javaVm = nullptr;
2628

29+
static bool isAttached(JavaVM *vm) {
30+
JNIEnv *env = nullptr;
31+
return vm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK;
32+
}
2733
/**
2834
Maintains the lifecycle of a JNIEnv.
2935
*/
@@ -57,7 +63,7 @@ namespace jni
5763
if (vm == nullptr)
5864
throw InitializationException("JNI not initialized");
5965

60-
if (vm->GetEnv((void**)&_env, JNI_VERSION_1_2) != JNI_OK)
66+
if (!isAttached(vm))
6167
{
6268
#ifdef __ANDROID__
6369
if (vm->AttachCurrentThread(&_env, nullptr) != 0)
@@ -150,8 +156,17 @@ namespace jni
150156
{
151157
static thread_local ScopedEnv env;
152158

159+
if (env.get() != nullptr && !isAttached(javaVm))
160+
{
161+
// we got detached, so clear it.
162+
// will be re-populated from static javaVm below.
163+
env = ScopedEnv{};
164+
}
165+
153166
if (env.get() == nullptr)
167+
{
154168
env.init(javaVm);
169+
}
155170

156171
return env.get();
157172
}
@@ -1270,7 +1285,57 @@ namespace jni
12701285

12711286
typedef jint (JNICALL *CreateVm_t)(JavaVM**, void**, void*);
12721287

1288+
#ifndef _WIN32
1289+
static bool fileExists(const std::string& filePath)
1290+
{
1291+
return access(filePath.c_str(), F_OK) != -1;
1292+
}
1293+
1294+
template <size_t N>
1295+
static ssize_t readlink_safe(const char *pathname, char (&output)[N]) {
1296+
auto len = readlink(pathname, output, N - 1);
1297+
if (len > 0) {
1298+
output[len] = '\0';
1299+
}
1300+
return len;
1301+
}
12731302

1303+
static std::pair<ssize_t, std::string>
1304+
readlink_as_string(const char *pathname) {
1305+
char buf[2048] = {};
1306+
auto len = readlink_safe(pathname, buf);
1307+
if (len <= 0) {
1308+
return {len, {}};
1309+
}
1310+
return {len, std::string{buf, static_cast<size_t>(len)}};
1311+
}
1312+
static std::string readlink_deep(const char *pathname) {
1313+
std::string prev{pathname};
1314+
ssize_t len = 0;
1315+
std::string next;
1316+
while (true) {
1317+
std::tie(len, next) = readlink_as_string(prev.c_str());
1318+
if (!next.empty()) {
1319+
prev = next;
1320+
} else {
1321+
return prev;
1322+
}
1323+
}
1324+
}
1325+
1326+
static std::string drop_path_components(const std::string & path, size_t num_components) {
1327+
size_t pos = std::string::npos;
1328+
size_t slash_pos = std::string::npos;
1329+
for (size_t i = 0; i < num_components; ++i) {
1330+
slash_pos = path.find_last_of('/', pos);
1331+
if (slash_pos == std::string::npos || slash_pos == 0) {
1332+
return {};
1333+
}
1334+
pos = slash_pos - 1;
1335+
}
1336+
return std::string{path.c_str(), slash_pos};
1337+
}
1338+
#endif
12741339
static std::string detectJvmPath()
12751340
{
12761341
std::string result;
@@ -1321,7 +1386,7 @@ namespace jni
13211386
javaHome + "\\bin\\server\\jvm.dll"
13221387
};
13231388

1324-
for (auto i : options)
1389+
for (auto const& i : options)
13251390
if (fileExists(i))
13261391
return i;
13271392
}
@@ -1338,6 +1403,28 @@ namespace jni
13381403
#endif
13391404
result = libJvmPath;
13401405
} else {
1406+
std::string path = readlink_deep("/usr/bin/java");
1407+
if (!path.empty()) {
1408+
// drop bin and java
1409+
auto javaHome = drop_path_components(path, 2);
1410+
if (!javaHome.empty()) {
1411+
std::string options[] = {
1412+
javaHome + "/jre/lib/amd64/server/libjvm.so",
1413+
javaHome + "/jre/lib/amd64/client/libjvm.so",
1414+
javaHome + "/jre/lib/server/libjvm.so",
1415+
javaHome + "/jre/lib/client/libjvm.so",
1416+
javaHome + "/lib/server/libjvm.so",
1417+
javaHome + "/lib/client/libjvm.so",
1418+
};
1419+
1420+
for (auto const &i : options) {
1421+
fprintf(stderr, "trying %s\n", i.c_str());
1422+
if (fileExists(i)) {
1423+
return i;
1424+
}
1425+
}
1426+
}
1427+
}
13411428
// Best guess so far.
13421429
result = "/usr/lib/jvm/default-java/jre/lib/amd64/server/libjvm.so";
13431430
}
@@ -1388,6 +1475,7 @@ namespace jni
13881475
}
13891476

13901477
#else
1478+
fprintf(stderr, "opening %s\n", path.c_str());
13911479

13921480
void* lib = ::dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
13931481

src/external/jnipp/jnipp.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,20 @@ namespace jni
175175
value_t values[sizeof...(TArgs)];
176176
};
177177

178+
/* specialization for empty array - no args. Avoids "empty array" warning. */
179+
template <>
180+
class ArgArray<>
181+
{
182+
public:
183+
ArgArray() {
184+
std::memset(this, 0, sizeof(ArgArray<>));
185+
}
186+
187+
~ArgArray() {
188+
}
189+
190+
value_t values[1];
191+
};
178192
long getArrayLength(jarray array);
179193
}
180194

src/external/jnipp/makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ endif
1515

1616
JAVA_HOME ?= /usr/lib/jvm/default-java
1717

18-
CXXFLAGS=-I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(OS_NAME) -ldl -std=c++11
18+
CXXFLAGS=-I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(OS_NAME) -ldl -std=c++11 -Wall -g
1919

2020
SRC=jnipp.o main.o
2121
VPATH=tests

src/external/jnipp/tests/main.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ TEST(Object_moveAssignmentOperator)
249249
ASSERT(b.isNull());
250250
}
251251

252+
TEST(Object_nullary_construct_from_signature)
253+
{
254+
jni::Class String("java/lang/String");
255+
jni::method_t init = String.getMethod("<init>", "()V");
256+
jni::Object i = String.newInstance(init);
257+
ASSERT(!i.isNull());
258+
jni::internal::ArgArray<> a;
259+
}
260+
252261
TEST(Object_call)
253262
{
254263
jni::Class Integer("java/lang/Integer");
@@ -575,6 +584,7 @@ int main()
575584

576585
// jni::Object Tests
577586
RUN_TEST(Object_defaultConstructor_isNull);
587+
RUN_TEST(Object_nullary_construct_from_signature);
578588
RUN_TEST(Object_copyConstructorIsSameObject);
579589
RUN_TEST(Object_moveConstructor);
580590
RUN_TEST(Object_copyAssignmentOperator);

0 commit comments

Comments
 (0)