Skip to content

Commit 5e421bb

Browse files
committed
jnipp: Upstream updates, including fixes for crashes.
Fixes issues related to manual attaching/detaching thread from VM.
1 parent 2949efb commit 5e421bb

File tree

8 files changed

+185
-32
lines changed

8 files changed

+185
-32
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
- pr.285.gh.OpenXR-SDK-Source
3+
---
4+
Android loader: Update vendored jnipp project, including crash/exception fixes if an application manually attached or detached a thread.

src/external/jnipp/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2021, Collabora, Ltd.
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
cmake_minimum_required(VERSION 3.10.2)
6+
project(jnipp)
7+
8+
find_package(JNI REQUIRED)
9+
include(CTest)
10+
11+
add_library(jnipp jnipp.cpp)
12+
target_include_directories(
13+
jnipp
14+
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
15+
PRIVATE ${JNI_INCLUDE_DIRS})
16+
target_link_libraries(jnipp PUBLIC ${CMAKE_DL_LIBS})
17+
18+
add_subdirectory(tests)

src/external/jnipp/jnipp.cpp

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ namespace jni
2626
static std::atomic_bool isVm(false);
2727
static JavaVM* javaVm = nullptr;
2828

29+
static bool getEnv(JavaVM *vm, JNIEnv **env) {
30+
return vm->GetEnv((void **)env, JNI_VERSION_1_2) == JNI_OK;
31+
}
32+
2933
static bool isAttached(JavaVM *vm) {
3034
JNIEnv *env = nullptr;
31-
return vm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK;
35+
return getEnv(vm, &env);
3236
}
3337
/**
3438
Maintains the lifecycle of a JNIEnv.
@@ -63,7 +67,7 @@ namespace jni
6367
if (vm == nullptr)
6468
throw InitializationException("JNI not initialized");
6569

66-
if (!isAttached(vm))
70+
if (!getEnv(vm, &_env))
6771
{
6872
#ifdef __ANDROID__
6973
if (vm->AttachCurrentThread(&_env, nullptr) != 0)
@@ -368,20 +372,20 @@ namespace jni
368372
return _handle == nullptr || env()->IsSameObject(_handle, nullptr);
369373
}
370374

371-
template <> void Object::callMethod(method_t method, internal::value_t* args) const
375+
void Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<void> const&) const
372376
{
373377
env()->CallVoidMethodA(_handle, method, (jvalue*) args);
374378
handleJavaExceptions();
375379
}
376380

377-
template <> bool Object::callMethod(method_t method, internal::value_t* args) const
381+
bool Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<bool> const&) const
378382
{
379383
auto result = env()->CallBooleanMethodA(_handle, method, (jvalue*) args);
380384
handleJavaExceptions();
381385
return result != 0;
382386
}
383387

384-
template <> bool Object::get(field_t field) const
388+
bool Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<bool> const&) const
385389
{
386390
return env()->GetBooleanField(_handle, field) != 0;
387391
}
@@ -391,122 +395,122 @@ namespace jni
391395
env()->SetBooleanField(_handle, field, value);
392396
}
393397

394-
template <> byte_t Object::callMethod(method_t method, internal::value_t* args) const
398+
byte_t Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<byte_t> const&) const
395399
{
396400
auto result = env()->CallByteMethodA(_handle, method, (jvalue*) args);
397401
handleJavaExceptions();
398402
return result;
399403
}
400404

401-
template <> wchar_t Object::callMethod(method_t method, internal::value_t* args) const
405+
wchar_t Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<wchar_t> const&) const
402406
{
403407
auto result = env()->CallCharMethodA(_handle, method, (jvalue*) args);
404408
handleJavaExceptions();
405409
return result;
406410
}
407411

408-
template <> short Object::callMethod(method_t method, internal::value_t* args) const
412+
short Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<short> const&) const
409413
{
410414
auto result = env()->CallShortMethodA(_handle, method, (jvalue*) args);
411415
handleJavaExceptions();
412416
return result;
413417
}
414418

415-
template <> int Object::callMethod(method_t method, internal::value_t* args) const
419+
int Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<int> const&) const
416420
{
417421
auto result = env()->CallIntMethodA(_handle, method, (jvalue*) args);
418422
handleJavaExceptions();
419423
return result;
420424
}
421425

422-
template <> long long Object::callMethod(method_t method, internal::value_t* args) const
426+
long long Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<long long> const&) const
423427
{
424428
auto result = env()->CallLongMethodA(_handle, method, (jvalue*) args);
425429
handleJavaExceptions();
426430
return result;
427431
}
428432

429-
template <> float Object::callMethod(method_t method, internal::value_t* args) const
433+
float Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<float> const&) const
430434
{
431435
auto result = env()->CallFloatMethodA(_handle, method, (jvalue*) args);
432436
handleJavaExceptions();
433437
return result;
434438
}
435439

436-
template <> double Object::callMethod(method_t method, internal::value_t* args) const
440+
double Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<double> const&) const
437441
{
438442
auto result = env()->CallDoubleMethodA(_handle, method, (jvalue*) args);
439443
handleJavaExceptions();
440444
return result;
441445
}
442446

443-
template <> std::string Object::callMethod(method_t method, internal::value_t* args) const
447+
std::string Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::string> const&) const
444448
{
445449
auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args);
446450
handleJavaExceptions();
447451
return toString(result);
448452
}
449453

450-
template <> std::wstring Object::callMethod(method_t method, internal::value_t* args) const
454+
std::wstring Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::wstring> const&) const
451455
{
452456
auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args);
453457
handleJavaExceptions();
454458
return toWString(result);
455459
}
456460

457-
template <> jni::Object Object::callMethod(method_t method, internal::value_t* args) const
461+
jni::Object Object::callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jni::Object> const&) const
458462
{
459463
auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args);
460464
handleJavaExceptions();
461465
return Object(result, DeleteLocalInput);
462466
}
463467

464-
template <> byte_t Object::get(field_t field) const
468+
byte_t Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<byte_t> const&) const
465469
{
466470
return env()->GetByteField(_handle, field);
467471
}
468472

469-
template <> wchar_t Object::get(field_t field) const
473+
wchar_t Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<wchar_t> const&) const
470474
{
471475
return env()->GetCharField(_handle, field);
472476
}
473477

474-
template <> short Object::get(field_t field) const
478+
short Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<short> const&) const
475479
{
476480
return env()->GetShortField(_handle, field);
477481
}
478482

479-
template <> int Object::get(field_t field) const
483+
int Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<int> const&) const
480484
{
481485
return env()->GetIntField(_handle, field);
482486
}
483487

484-
template <> long long Object::get(field_t field) const
488+
long long Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<long long> const&) const
485489
{
486490
return env()->GetLongField(_handle, field);
487491
}
488492

489-
template <> float Object::get(field_t field) const
493+
float Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<float> const&) const
490494
{
491495
return env()->GetFloatField(_handle, field);
492496
}
493497

494-
template <> double Object::get(field_t field) const
498+
double Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<double> const&) const
495499
{
496500
return env()->GetDoubleField(_handle, field);
497501
}
498502

499-
template <> std::string Object::get(field_t field) const
503+
std::string Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<std::string> const&) const
500504
{
501505
return toString(env()->GetObjectField(_handle, field));
502506
}
503507

504-
template <> std::wstring Object::get(field_t field) const
508+
std::wstring Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<std::wstring> const&) const
505509
{
506510
return toWString(env()->GetObjectField(_handle, field));
507511
}
508512

509-
template <> Object Object::get(field_t field) const
513+
Object Object::getFieldValue(field_t field, internal::ReturnTypeWrapper<Object> const&) const
510514
{
511515
return Object(env()->GetObjectField(_handle, field), DeleteLocalInput);
512516
}
@@ -1475,7 +1479,6 @@ namespace jni
14751479
}
14761480

14771481
#else
1478-
fprintf(stderr, "opening %s\n", path.c_str());
14791482

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

src/external/jnipp/jnipp.h

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,17 @@ namespace jni
190190
value_t values[1];
191191
};
192192
long getArrayLength(jarray array);
193+
194+
/**
195+
* @brief Used as a tag type for dispatching internally based on return type.
196+
*
197+
* @tparam T The type to wrap.
198+
*/
199+
template<typename T>
200+
struct ReturnTypeWrapper
201+
{
202+
using type = T;
203+
};
193204
}
194205

195206
/**
@@ -296,7 +307,7 @@ namespace jni
296307
\return The method's return value.
297308
*/
298309
template <class TReturn>
299-
TReturn call(method_t method) const { return callMethod<TReturn>(method, nullptr); }
310+
TReturn call(method_t method) const { return callMethod(method, nullptr, internal::ReturnTypeWrapper<TReturn>{}); }
300311

301312
/**
302313
Calls the method on this Object with the given name, and no arguments.
@@ -326,7 +337,7 @@ namespace jni
326337
template <class TReturn, class... TArgs>
327338
TReturn call(method_t method, const TArgs&... args) const {
328339
internal::ArgArray<TArgs...> transform(args...);
329-
return callMethod<TReturn>(method, transform.values);
340+
return callMethod(method, transform.values, internal::ReturnTypeWrapper<TReturn>{});
330341
}
331342

332343
/**
@@ -356,7 +367,11 @@ namespace jni
356367
\return The field's value.
357368
*/
358369
template <class TType>
359-
TType get(field_t field) const;
370+
TType get(field_t field) const {
371+
// If you get a compile error here, then you've asked for a type
372+
// we don't know how to get from JNI directly.
373+
return getFieldValue(field, internal::ReturnTypeWrapper<TType>{});
374+
}
360375

361376
/**
362377
Gets a field value from this Object. The field must belong to the
@@ -424,7 +439,33 @@ namespace jni
424439
method_t getMethod(const char* name, const char* signature) const;
425440
method_t getMethod(const char* nameAndSignature) const;
426441
field_t getField(const char* name, const char* signature) const;
427-
template <class TType> TType callMethod(method_t method, internal::value_t* values) const;
442+
443+
void callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<void> const&) const;
444+
bool callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<bool> const&) const;
445+
byte_t callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<byte_t> const&) const;
446+
wchar_t callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<wchar_t> const&) const;
447+
short callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<short> const&) const;
448+
int callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<int> const&) const;
449+
long long callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<long long> const&) const;
450+
float callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<float> const&) const;
451+
double callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<double> const&) const;
452+
std::string callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::string> const&) const;
453+
std::wstring callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::wstring> const&) const;
454+
jni::Object callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jni::Object> const&) const;
455+
456+
457+
void getFieldValue(field_t field, internal::ReturnTypeWrapper<void> const&) const;
458+
bool getFieldValue(field_t field, internal::ReturnTypeWrapper<bool> const&) const;
459+
byte_t getFieldValue(field_t field, internal::ReturnTypeWrapper<byte_t> const&) const;
460+
wchar_t getFieldValue(field_t field, internal::ReturnTypeWrapper<wchar_t> const&) const;
461+
short getFieldValue(field_t field, internal::ReturnTypeWrapper<short> const&) const;
462+
int getFieldValue(field_t field, internal::ReturnTypeWrapper<int> const&) const;
463+
long long getFieldValue(field_t field, internal::ReturnTypeWrapper<long long> const&) const;
464+
float getFieldValue(field_t field, internal::ReturnTypeWrapper<float> const&) const;
465+
double getFieldValue(field_t field, internal::ReturnTypeWrapper<double> const&) const;
466+
std::string getFieldValue(field_t field, internal::ReturnTypeWrapper<std::string> const&) const;
467+
std::wstring getFieldValue(field_t field, internal::ReturnTypeWrapper<std::wstring> const&) const;
468+
jni::Object getFieldValue(field_t field, internal::ReturnTypeWrapper<jni::Object> const&) const;
428469

429470
// Instance Variables
430471
jobject _handle;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2021, Collabora, Ltd.
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
add_executable(main_test main.cpp testing.h)
6+
target_link_libraries(main_test PRIVATE jnipp)
7+
add_test(NAME main_test COMMAND main_test)
8+
9+
add_executable(external_create external_create.cpp testing.h)
10+
target_link_libraries(external_create PUBLIC jnipp ${JNI_LIBRARIES})
11+
target_include_directories(external_create PUBLIC ${JNI_INCLUDE_DIRS})
12+
add_test(NAME external_create COMMAND external_create)
13+
14+
15+
add_executable(external_detach external_detach.cpp testing.h)
16+
target_link_libraries(external_detach PUBLIC jnipp ${JNI_LIBRARIES})
17+
target_include_directories(external_detach PUBLIC ${JNI_INCLUDE_DIRS})
18+
add_test(NAME external_detach COMMAND external_detach)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Project Dependencies
2+
#include <jni.h>
3+
#include <jnipp.h>
4+
5+
// Standard Dependencies
6+
#include <cmath>
7+
8+
// Local Dependencies
9+
#include "testing.h"
10+
11+
/*
12+
jni::Vm Tests
13+
*/
14+
TEST(Vm_externalCreateAndAttach) {
15+
JNIEnv *env;
16+
JavaVMInitArgs args = {};
17+
args.version = JNI_VERSION_1_2;
18+
JavaVM *javaVm{};
19+
auto ret = JNI_CreateJavaVM(&javaVm, (void **)&env, &args);
20+
ASSERT(ret == 0);
21+
22+
{
23+
jni::init(env);
24+
jni::Class cls("java/lang/String");
25+
}
26+
JavaVM *localVmPointer{};
27+
28+
ret = env->GetJavaVM(&localVmPointer);
29+
ASSERT(ret == 0);
30+
}
31+
32+
int main() {
33+
// jni::Vm Tests
34+
RUN_TEST(Vm_externalCreateAndAttach);
35+
36+
return 0;
37+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Project Dependencies
2+
#include <jni.h>
3+
#include <jnipp.h>
4+
5+
// Standard Dependencies
6+
#include <cmath>
7+
8+
// Local Dependencies
9+
#include "testing.h"
10+
11+
/*
12+
jni::Vm Tests
13+
*/
14+
TEST(Vm_externalDetach) {
15+
jni::Vm vm;
16+
17+
jni::Class cls("java/lang/String");
18+
19+
JNIEnv *env = (JNIEnv *)jni::env();
20+
JavaVM *localVmPointer{};
21+
22+
auto ret = env->GetJavaVM(&localVmPointer);
23+
ASSERT(ret == 0);
24+
ret = localVmPointer->DetachCurrentThread();
25+
ASSERT(ret == 0);
26+
27+
ASSERT(1);
28+
}
29+
30+
int main() {
31+
// jni::Vm Tests
32+
RUN_TEST(Vm_externalDetach);
33+
return 0;
34+
}

0 commit comments

Comments
 (0)