YSTest: JNI.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

JNI.cpp
浏览该文件的文档.
1 /*
2 © 2014-2016 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
29 #include "YCLib/YModules.h"
30 #include YFM_YCLib_JNI
31 #if YF_Use_JNI
32 #include YFM_YCLib_Debug // for platform::Descriptions, platform::Deref,
33 // ystdex::replace_cast;
34 #include YFM_YCLib_POSIXThread
35 #include <ystdex/exception.h> // for ystdex::unsupported;
36
37 namespace platform_ex
38 {
39
40 using namespace platform::Descriptions;
42 using platform::Deref;
43
44 namespace JNI
45 {
46
47 #define YCL_RaiseJNIFailure(_str) \
48 (YTraceDe(Err, _str), throw platform_ex::JNI::JNIException(_str))
49
51 namespace
52 {
53
55 pair<::JNIEnv&, bool>
56 FetchJNIEnvRef(::JavaVM& vm, ::jint version)
57 {
58 void* p_env;
59 int status(vm.GetEnv(&p_env, version));
60 auto& p_jni(ystdex::replace_cast<::JNIEnv*&>(p_env));
61
62 if(status == JNI_EDETACHED)
63 {
64 YTraceDe(Debug, "JNI thread has not attached.");
65 status = vm.AttachCurrentThread(&p_jni, {});
66 if(status != JNI_OK)
67 {
68 YTraceDe(Err, "Status = %d.", status);
69 YCL_RaiseJNIFailure("Failed attaching JNI thread.");
70 }
71 else
72 YTraceDe(Informative, "JNI thread attached.");
73 TryExpr(JNIBase::EnsureDetachJNIAtThreadExit(vm, Deref(p_jni)))
74 CatchIgnore(ystdex::unsupported&)
75 }
76 else if(status != JNI_OK)
77 {
78 YTraceDe(Err, "Status = %d.", status);
79 YCL_RaiseJNIFailure("Failed getting JNI environment.");
80 }
81 YAssertNonnull(p_jni);
82 return {*p_jni, status == JNI_EDETACHED};
83 }
84
85 } // unnamed namespace;
86
87 JNIBase::JNIBase(::JavaVM& vm, ::jint version)
88 : JNIBase(vm, FetchJNIEnvRef(vm, version))
89 {}
90 JNIBase::~JNIBase()
91 {
92 if(owns)
93 vm_ref.get().DetachCurrentThread();
94 }
95
96 void
97 JNIBase::EnsureDetachJNIAtThreadExit(::JavaVM& vm, ::JNIEnv& env)
98 {
99 # if YF_Multithread == 1
100 # if YB_HAS_THREAD_LOCAL
101 ythread JNIBase guard(vm, env);
102 # elif YF_Use_POSIXThread
103
104 static TLSKey key([](void* p) ynothrow{
105 delete static_cast<JNIBase*>(p);
106 });
107
108 key.SetValue(new JNIBase(vm, {env, true}));
109 # else
110 throw ystdex::unsupported("Platform without TLS or POSIX thread "
111 " unsupported to automatically detach.");
112 # endif
113 # endif
114 }
115
116 void
117 JNIBase::ThrowOnException() ythrow(JNIException)
118 {
119 if(GetEnvRef().ExceptionCheck())
120 throw JNIException("A pending exception has occurred.");
121 }
122
123 } // namespace JNI;
124
125 } // namespace platform_ex;
126
127 #endif
128
ystdex::unsupported
异常：不支持的操作。
Definition: ystdex/exception.h:116
YTraceDe
#define YTraceDe(...)
YCLib 默认调试跟踪。
Definition: Debug.h:313
platform::Descriptions::Debug
Definition: YCommon.h:170
platform::Deref
yconstfn auto Deref(_type &&p) -> decltype(*p)
断言并解引用非空指针。
Definition: Debug.h:451
YAssertNonnull
#define YAssertNonnull(_expr)
Definition: cassert.h:120
CatchIgnore
#define CatchIgnore(_ex)
指定异常处理器忽略指定异常。
Definition: YBaseMacro.h:133
ythread
#define ythread
线程局部存储：若实现支持，指定为 thread_local 。
Definition: ydef.h:806
TryExpr
#define TryExpr(...)
指定表达式在 try 块中求值。
Definition: YBaseMacro.h:120
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:766
platform::if
if(!p) p
ystdex
特性测试宏。
Definition: ydef.h:822
YModules.h
exception.h
ythrow
#define ythrow(...)
YSLib 动态异常规范：根据是否使用异常规范宏指定或忽略动态异常规范。
Definition: ydef.h:817
platform::Descriptions::Err
Definition: YCommon.h:166
platform_ex
平台扩展命名空间。
Definition: Android.h:45
platform::Descriptions::Informative
Definition: YCommon.h:169
platform::Descriptions
平台描述空间。
Definition: YCommon.h:154
CHRLib::p
const auto p(d)