Merge pull request #86 from facebook/Fix-Android
[WIP][HELP]Fix android
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ website/build
|
||||
*.xcworkspace
|
||||
**/Pods/
|
||||
**/xcuserdata/
|
||||
build/
|
||||
yarn-error.log
|
||||
|
||||
# Android / Intellij
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
cmake_minimum_required (VERSION 3.6.0)
|
||||
project(sonar CXX C)
|
||||
project(sonar CXX)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
set(PACKAGE_NAME "sonar")
|
||||
|
||||
add_compile_options(-DFOLLY_NO_CONFIG
|
||||
add_compile_options(-DSONAR_OSS=1
|
||||
-DFOLLY_NO_CONFIG
|
||||
-DSONAR_JNI_EXTERNAL=1
|
||||
-DFB_SONARKIT_ENABLED=1
|
||||
-DFOLLY_HAVE_MEMRCHR
|
||||
@@ -14,7 +17,6 @@ add_compile_options(-DFOLLY_NO_CONFIG
|
||||
-DFOLLY_HAVE_PREADV=0
|
||||
-frtti
|
||||
-fexceptions
|
||||
-std=c++14
|
||||
-Wno-error
|
||||
-Wno-unused-local-typedefs
|
||||
-Wno-unused-variable
|
||||
@@ -29,13 +31,13 @@ add_library(${PACKAGE_NAME} SHARED ${SOURCES})
|
||||
target_include_directories(${PACKAGE_NAME} PUBLIC "./")
|
||||
|
||||
set(libjnihack_DIR ${CMAKE_SOURCE_DIR}/../libs/jni-hack/)
|
||||
set(libfbjni_DIR ${CMAKE_SOURCE_DIR}/../libs/fbjni/src/main/cpp/include/)
|
||||
set(libfbjni_DIR ${CMAKE_SOURCE_DIR}/../libs/fbjni/)
|
||||
set(libsonar_DIR ${CMAKE_SOURCE_DIR}/../xplat/)
|
||||
set(third_party_ndk build/third-party-ndk)
|
||||
set(third_party_ndk ${PROJECT_SOURCE_DIR}/build/third-party-ndk)
|
||||
set(libfolly_DIR ${third_party_ndk}/folly/)
|
||||
set(glog_DIR ${third_party_ndk}/glog)
|
||||
set(BOOST_DIR ${third_party_ndk}/boost/boost_1_63_0/)
|
||||
|
||||
set(LIBEVENT_DIR ${third_party_ndk}/LibEvent/libevent-release-2.1.9/)
|
||||
|
||||
set(build_DIR ${CMAKE_SOURCE_DIR}/build)
|
||||
|
||||
@@ -46,11 +48,14 @@ set(libfolly_build_DIR ${build_DIR}/libfolly/${ANDROID_ABI})
|
||||
file(MAKE_DIRECTORY ${build_DIR})
|
||||
|
||||
add_subdirectory(${libsonar_DIR} ${libsonar_build_DIR})
|
||||
add_subdirectory(${libfbjni_DIR}/../ ${fbjni_build_DIR})
|
||||
add_subdirectory(${libfbjni_DIR} ${fbjni_build_DIR})
|
||||
|
||||
target_include_directories(${PACKAGE_NAME} PRIVATE
|
||||
${libjnihack_DIR}
|
||||
${libfbjni_DIR}
|
||||
${libfbjni_DIR}/cxx/
|
||||
${libfbjni_DIR}/cxx/fbjni
|
||||
${libfbjni_DIR}/cxx/fbjni/detail
|
||||
${libfbjni_DIR}/cxx/lyra
|
||||
${libsonar_DIR}
|
||||
${libfolly_DIR}
|
||||
${glog_DIR}
|
||||
@@ -58,6 +63,9 @@ target_include_directories(${PACKAGE_NAME} PRIVATE
|
||||
${glog_DIR}/glog-0.3.5/src/
|
||||
${BOOST_DIR}
|
||||
${BOOST_DIR}/../
|
||||
${LIBEVENT_DIR}/
|
||||
${LIBEVENT_DIR}/include/
|
||||
${LIBEVENT_DIR}/include/event2
|
||||
)
|
||||
|
||||
target_link_libraries(${PACKAGE_NAME} fb sonarcpp)
|
||||
target_link_libraries(${PACKAGE_NAME} sonarfb sonarcpp)
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifdef SONAR_OSS
|
||||
#include <fbjni/fbjni.h>
|
||||
#else
|
||||
#include <fb/fbjni.h>
|
||||
#endif
|
||||
|
||||
#include <folly/json.h>
|
||||
#include <folly/io/async/EventBase.h>
|
||||
|
||||
@@ -74,13 +74,13 @@ task prepareDoubleConversion(dependsOn: [downloadDoubleConversion], type: Copy)
|
||||
task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src 'https://github.com/react-native-community/boost-for-react-native/releases/download/v1.63.0-0/boost_1_63_0.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
overwrite true
|
||||
dest new File(downloadsDir, 'boost_1_63_0.tar.gz')
|
||||
}
|
||||
|
||||
task prepareBoost(dependsOn: [downloadBoost], type: Copy) {
|
||||
from tarTree(resources.gzip(downloadBoost.dest))
|
||||
include 'boost_1_63_0/boost/**/*.hpp', 'boost/boost/**/*.hpp'
|
||||
include 'boost_1_63_0/boost/**/*.hpp', 'boost_1_63_0/boost/**/*.h', 'boost/boost/**/*.hpp', 'boost/boost/**/*.h'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/boost"
|
||||
doLast {
|
||||
@@ -89,26 +89,102 @@ task prepareBoost(dependsOn: [downloadBoost], type: Copy) {
|
||||
}
|
||||
|
||||
task downloadFolly(dependsOn: createNativeDepsDirectories, type: Download) {
|
||||
src 'https://github.com/facebook/folly/archive/v2018.05.21.00.tar.gz'
|
||||
src 'https://github.com/facebook/folly/archive/v2018.06.18.00.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'folly-2018.05.21.00.tar.gz');
|
||||
dest new File(downloadsDir, 'folly-2018.06.18.00.tar.gz');
|
||||
}
|
||||
|
||||
task prepareFolly(dependsOn: [downloadFolly], type: Copy) {
|
||||
from tarTree(downloadFolly.dest)
|
||||
from './third-party/folly/'
|
||||
include 'folly-2018.05.21.00/folly/**/*', 'build.gradle', 'CMakeLists.txt', 'ApplicationManifest.xml'
|
||||
eachFile {fname -> fname.path = (fname.path - "folly-2018.05.21.00/")}
|
||||
from './third-party/Folly/'
|
||||
include 'folly-2018.06.18.00/folly/**/*', 'build.gradle', 'CMakeLists.txt', 'ApplicationManifest.xml'
|
||||
eachFile {fname -> fname.path = (fname.path - "folly-2018.06.18.00/")}
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/folly"
|
||||
}
|
||||
|
||||
//TODO: Get rid off this hack.
|
||||
task finalizeFolly(dependsOn: [prepareFolly], type: Copy) {
|
||||
from './third-party/Folly/'
|
||||
include 'AsyncServerSocket.cpp'
|
||||
into "$thirdPartyNdkDir/folly/folly/io/async/"
|
||||
}
|
||||
|
||||
task downloadLibEvent(dependsOn: [], type: Download) {
|
||||
src 'https://github.com/priteshrnandgaonkar/libevent/archive/release-2.1.9.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'libevent-release-2.1.9.tar.gz');
|
||||
}
|
||||
|
||||
task prepareLibEvent(dependsOn: [downloadLibEvent], type: Copy) {
|
||||
from tarTree(downloadLibEvent.dest)
|
||||
from './third-party/LibEvent/'
|
||||
include 'libevent-release-2.1.9/**/*', 'build.gradle', 'ApplicationManifest.xml'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/LibEvent"
|
||||
}
|
||||
|
||||
task finalizeEvent(dependsOn: [prepareLibEvent], type: Copy) {
|
||||
from './third-party/LibEvent/'
|
||||
include 'event-config.h'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/LibEvent/libevent-release-2.1.9/include/event2/"
|
||||
}
|
||||
|
||||
task finalizeEvent2(dependsOn: [finalizeEvent], type: Copy) {
|
||||
from './third-party/LibEvent/'
|
||||
include 'libs/**/*'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/LibEvent/"
|
||||
}
|
||||
|
||||
task downloadOpenSSL(dependsOn: [], type: Download) {
|
||||
src 'https://github.com/priteshrnandgaonkar/openssl-android/archive/1.0.0.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'openssl-android-1.0.0.tar.gz');
|
||||
}
|
||||
|
||||
task prepareOpenSSL(dependsOn: [downloadOpenSSL], type: Copy) {
|
||||
from tarTree(downloadOpenSSL.dest)
|
||||
from './third-party/OpenSSL/'
|
||||
include 'openssl-android-1.0.0/**/*', 'libs/**/*'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/OpenSSL/"
|
||||
}
|
||||
|
||||
task finalizeOpenSSL(dependsOn: [prepareOpenSSL], type: Copy) {
|
||||
from './third-party/OpenSSL/'
|
||||
include 'build.gradle', 'ApplicationManifest.xml'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/OpenSSL/openssl-android-1.0.0/"
|
||||
}
|
||||
|
||||
task downloadRSocket(dependsOn: [], type: Download) {
|
||||
src 'https://github.com/priteshrnandgaonkar/rsocket-cpp/archive/0.10.1.tar.gz'
|
||||
onlyIfNewer true
|
||||
overwrite false
|
||||
dest new File(downloadsDir, 'rsocket-cpp-0.10.1.tar.gz');
|
||||
}
|
||||
|
||||
task prepareRSocket(dependsOn: [downloadRSocket], type: Copy) {
|
||||
from tarTree(downloadRSocket.dest)
|
||||
from './third-party/RSocket/'
|
||||
include 'rsocket-cpp-0.10.1/**/*', 'build.gradle', 'ApplicationManifest.xml', 'CMakeLists.txt'
|
||||
includeEmptyDirs = false
|
||||
into "$thirdPartyNdkDir/RSocket"
|
||||
}
|
||||
|
||||
task prepareAllLibs() {
|
||||
dependsOn finalizeGlog
|
||||
dependsOn prepareDoubleConversion
|
||||
dependsOn prepareBoost
|
||||
dependsOn prepareFolly
|
||||
dependsOn finalizeFolly
|
||||
dependsOn finalizeEvent
|
||||
dependsOn finalizeOpenSSL
|
||||
dependsOn prepareRSocket
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -120,7 +196,7 @@ android {
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
buildConfigField "boolean", "IS_INTERNAL_BUILD", 'true'
|
||||
ndk {
|
||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
abiFilters 'arm64-v8a', 'x86', 'armeabi-v7a'
|
||||
stl 'c++_shared'
|
||||
}
|
||||
|
||||
@@ -141,6 +217,9 @@ android {
|
||||
srcDir 'android'
|
||||
srcDir 'core'
|
||||
srcDir 'plugins'
|
||||
exclude 'console/ConsoleSonarPlugin.java'
|
||||
exclude 'console/JavascriptEnvironment.java'
|
||||
exclude 'console/JavascriptSession.java'
|
||||
}
|
||||
res {
|
||||
srcDir 'res'
|
||||
@@ -163,8 +242,8 @@ android {
|
||||
implementation deps.supportAppCompat
|
||||
implementation deps.stetho
|
||||
implementation deps.okhttp3
|
||||
implementation 'com.facebook.litho:litho-core:0.15.0'
|
||||
implementation 'com.facebook.litho:litho-widget:0.15.0'
|
||||
implementation deps.lithoCore
|
||||
implementation deps.lithoWidget
|
||||
implementation 'org.mozilla:rhino:1.7.10'
|
||||
}
|
||||
}
|
||||
|
||||
4
android/res/values/ids.xml
Normal file
4
android/res/values/ids.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item type="id" name="sonar_skip_view_traversal"/>
|
||||
</resources>
|
||||
@@ -22,17 +22,21 @@ android {
|
||||
res {
|
||||
srcDir 'res'
|
||||
}
|
||||
}
|
||||
}
|
||||
packagingOptions {
|
||||
pickFirst 'lib/armeabi-v7a/libfb.so'
|
||||
pickFirst 'lib/x86/libfb.so'
|
||||
pickFirst 'lib/x86_64/libfb.so'
|
||||
pickFirst 'lib/arm64-v8a/libfb.so'
|
||||
jniLibs.srcDirs = ['../third-party/OpenSSL/libs']
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
pickFirst 'lib/armeabi-v7a/libsonarfb.so'
|
||||
pickFirst 'lib/x86/libsonarfb.so'
|
||||
pickFirst 'lib/x86_64/libsonarfb.so'
|
||||
pickFirst 'lib/arm64-v8a/libsonarfb.so'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation deps.supportAppCompat
|
||||
implementation deps.supportConstraintLayout
|
||||
@@ -52,10 +56,10 @@ dependencies {
|
||||
|
||||
// For integration with Fresco
|
||||
implementation deps.lithoFresco
|
||||
|
||||
// For testing
|
||||
testImplementation deps.lithoTesting
|
||||
|
||||
implementation deps.okhttp3
|
||||
implementation project(':android')
|
||||
implementation project(':fbjni')
|
||||
}
|
||||
|
||||
@@ -4,15 +4,19 @@ package com.facebook.sonar.sample;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import java.util.List;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import com.facebook.litho.ComponentContext;
|
||||
import com.facebook.litho.LithoView;
|
||||
import android.util.Log;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final ComponentContext c = new ComponentContext(this);
|
||||
setContentView(
|
||||
LithoView.create(
|
||||
|
||||
@@ -7,8 +7,13 @@ import android.net.Network;
|
||||
import android.support.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import com.facebook.litho.sonar.LithoSonarDescriptors;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.facebook.sonar.plugins.inspector.DescriptorMapping;
|
||||
import com.facebook.sonar.plugins.inspector.InspectorSonarPlugin;
|
||||
import com.facebook.sonar.android.utils.SonarUtils;
|
||||
import com.facebook.sonar.android.AndroidSonarClient;
|
||||
import com.facebook.sonar.core.SonarClient;
|
||||
|
||||
@@ -6,7 +6,6 @@ set(PACKAGE_NAME doubleconversion)
|
||||
set(doubleconversion_DIR double-conversion-3.0.0/double-conversion)
|
||||
include_directories(${doubleconversion_DIR})
|
||||
file(GLOB SRCFILES ${doubleconversion_DIR}/*.cc)
|
||||
message(STATUS "SRC FILES :- " ${SRCFILES})
|
||||
add_library(${PACKAGE_NAME} SHARED ${SRCFILES})
|
||||
install(TARGETS ${PACKAGE_NAME} DESTINATION ./build/)
|
||||
target_link_libraries(${PACKAGE_NAME})
|
||||
|
||||
1103
android/third-party/Folly/AsyncServerSocket.cpp
vendored
Normal file
1103
android/third-party/Folly/AsyncServerSocket.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
71
android/third-party/Folly/CMakeLists.txt
vendored
71
android/third-party/Folly/CMakeLists.txt
vendored
@@ -3,10 +3,11 @@ cmake_minimum_required (VERSION 3.6.0)
|
||||
PROJECT(folly CXX)
|
||||
enable_language(CXX)
|
||||
set(PACKAGE_NAME folly)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(FOLLY_DIR ${PROJECT_SOURCE_DIR}/folly)
|
||||
|
||||
|
||||
list(APPEND dir_list ./)
|
||||
list(APPEND dir_list ${FOLLY_DIR}/lang)
|
||||
list(APPEND dir_list ${FOLLY_DIR}/hash/)
|
||||
@@ -15,14 +16,21 @@ list(APPEND dir_list ${FOLLY_DIR}/memory/detail)
|
||||
|
||||
set(BOOST_DIR ../boost/boost_1_63_0/)
|
||||
set(GLOG_DIR ../glog/)
|
||||
set(OPENSSL_DIR ../OpenSSL/openssl-android-1.0.0/)
|
||||
set(LIBEVENT_DIR ../LibEvent/libevent-release-2.1.9/)
|
||||
set(DOUBLECONVERSION_DIR ../double-conversion/double-conversion-3.0.0/)
|
||||
|
||||
list(APPEND dir_list ${BOOST_DIR})
|
||||
list(APPEND dir_list ${BOOST_DIR}/../)
|
||||
list(APPEND dir_list ${LIBEVENT_DIR}/)
|
||||
list(APPEND dir_list ${LIBEVENT_DIR}/include/)
|
||||
list(APPEND dir_list ${OPENSSL_DIR})
|
||||
|
||||
include_directories(${dir_list})
|
||||
|
||||
add_compile_options(
|
||||
-DFOLLY_HAVE_CLOCK_GETTIME=1
|
||||
-DFOLLY_HAVE_PTHREAD=1
|
||||
-DFOLLY_NO_CONFIG=1
|
||||
-DFOLLY_HAVE_MEMRCHR
|
||||
-DFOLLY_MOBILE=1
|
||||
@@ -31,7 +39,6 @@ add_compile_options(
|
||||
-DFOLLY_HAVE_PREADV=0
|
||||
-frtti
|
||||
-fexceptions
|
||||
-std=c++14
|
||||
-Wno-error
|
||||
-Wno-unused-local-typedefs
|
||||
-Wno-unused-variable
|
||||
@@ -40,8 +47,49 @@ add_compile_options(
|
||||
-Wno-return-type
|
||||
-Wno-tautological-constant-compare
|
||||
)
|
||||
|
||||
list(APPEND SRC_FILES ${FOLLY_DIR}/Executor.cpp
|
||||
file(GLOB SRC_FILES ${FOLLY_DIR}/portability/*.cpp
|
||||
${FOLLY_DIR}/io/async/ssl/*.cpp
|
||||
${FOLLY_DIR}/io/async/*.cpp
|
||||
${FOLLY_DIR}/detail/*.cpp
|
||||
${FOLLY_DIR}/synchronization/*.cpp
|
||||
${FOLLY_DIR}/lang/*.cpp
|
||||
${FOLLY_DIR}/hash/*.cpp
|
||||
${FOLLY_DIR}/hash/detail/*.cpp
|
||||
${FOLLY_DIR}/memory/*.cpp
|
||||
${FOLLY_DIR}/futures/*.cpp
|
||||
${FOLLY_DIR}/futures/detail/*.cpp
|
||||
${FOLLY_DIR}/experimental/hazptr/*.cpp
|
||||
${FOLLY_DIR}/executors/*.cpp
|
||||
${FOLLY_DIR}/concurrency/*.cpp
|
||||
${FOLLY_DIR}/ssl/*.cpp
|
||||
${FOLLY_DIR}/ssl/detail/*.cpp
|
||||
)
|
||||
list(APPEND SRC_FILES ${FOLLY_DIR}/io/async/HHWheelTimer.cpp
|
||||
${FOLLY_DIR}/io/async/AsyncPipe.cpp
|
||||
${FOLLY_DIR}/io/async/AsyncTimeout.cpp
|
||||
${FOLLY_DIR}/io/async/EventBaseManager.cpp
|
||||
${FOLLY_DIR}/io/async/TimeoutManager.cpp
|
||||
${FOLLY_DIR}/io/async/AsyncSocketException.cpp
|
||||
${FOLLY_DIR}/io/async/Request.cpp
|
||||
${FOLLY_DIR}/io/async/EventBase.cpp
|
||||
${FOLLY_DIR}/io/async/EventHandler.cpp
|
||||
${FOLLY_DIR}/io/async/VirtualEventBase.cpp
|
||||
${FOLLY_DIR}/io/ShutdownSocketSet.cpp
|
||||
${FOLLY_DIR}/SharedMutex.cpp
|
||||
${FOLLY_DIR}/ExceptionWrapper.cpp
|
||||
${FOLLY_DIR}/system/ThreadName.cpp
|
||||
${FOLLY_DIR}/io/IOBuf.cpp
|
||||
${FOLLY_DIR}/io/IOBufQueue.cpp
|
||||
${FOLLY_DIR}/File.cpp
|
||||
${FOLLY_DIR}/Random.cpp
|
||||
${FOLLY_DIR}/Singleton.cpp
|
||||
${FOLLY_DIR}/IPAddress.cpp
|
||||
${FOLLY_DIR}/IPAddressV4.cpp
|
||||
${FOLLY_DIR}/IPAddressV6.cpp
|
||||
${FOLLY_DIR}/MacAddress.cpp
|
||||
${FOLLY_DIR}/SocketAddress.cpp
|
||||
${FOLLY_DIR}/Executor.cpp
|
||||
${FOLLY_DIR}/FileUtil.cpp
|
||||
${FOLLY_DIR}/lang/ColdClass.cpp
|
||||
${FOLLY_DIR}/lang/Assume.cpp
|
||||
${FOLLY_DIR}/json.cpp
|
||||
@@ -55,6 +103,7 @@ list(APPEND SRC_FILES ${FOLLY_DIR}/Executor.cpp
|
||||
${FOLLY_DIR}/json_pointer.cpp
|
||||
${FOLLY_DIR}/FormatArg.cpp
|
||||
${FOLLY_DIR}/Format.cpp
|
||||
${FOLLY_DIR}/memory/detail/MallocImpl.cpp
|
||||
)
|
||||
|
||||
add_library(${PACKAGE_NAME} SHARED ${SRC_FILES})
|
||||
@@ -63,13 +112,18 @@ set(build_DIR ${CMAKE_SOURCE_DIR}/build)
|
||||
|
||||
set(libglog_build_DIR ${build_DIR}/libglog/${ANDROID_ABI})
|
||||
set(doubleconversion_build_DIR ${build_DIR}/doubleconversion/${ANDROID_ABI})
|
||||
set(libevent_build_DIR ${build_DIR}/libevent/${ANDROID_ABI})
|
||||
|
||||
|
||||
file(MAKE_DIRECTORY ${build_DIR})
|
||||
|
||||
add_subdirectory(${GLOG_DIR} ${libglog_build_DIR})
|
||||
add_subdirectory(${DOUBLECONVERSION_DIR} ${doubleconversion_build_DIR})
|
||||
|
||||
add_subdirectory(${LIBEVENT_DIR} ${libevent_build_DIR})
|
||||
target_include_directories(${PACKAGE_NAME} PRIVATE
|
||||
${OPENSSL_DIR}/jni/openssl-android/
|
||||
${OPENSSL_DIR}/jni/openssl-android/include
|
||||
${OPENSSL_DIR}/jni/openssl-android/include/openssl
|
||||
${BOOST_DIR}
|
||||
${BOOST_DIR}/../
|
||||
${GLOG_DIR}/../
|
||||
@@ -77,5 +131,10 @@ target_include_directories(${PACKAGE_NAME} PRIVATE
|
||||
${DOUBLECONVERSION_DIR})
|
||||
|
||||
|
||||
set(LIBEXTRA_PATH /Users/prit91/LocalDevTesting/sonar-upstream-proper/Sonar/android/build/third-party-ndk/LibEvent/.externalNativeBuild/cmake/debug/${ANDROID_ABI}/lib)
|
||||
set(OPENSSL_LINK_DIRECTORIES ${PROJECT_SOURCE_DIR}/../OpenSSL/libs/${ANDROID_ABI}/)
|
||||
find_path(OPENSSL_LIBRARY libssl.so HINTS ${OPENSSL_LINK_DIRECTORIES})
|
||||
|
||||
install(TARGETS ${PACKAGE_NAME} DESTINATION ./build/)
|
||||
target_link_libraries(${PACKAGE_NAME} glog double-conversion)
|
||||
|
||||
target_link_libraries(${PACKAGE_NAME} glog double-conversion ${OPENSSL_LINK_DIRECTORIES}/libssl.so ${OPENSSL_LINK_DIRECTORIES}/libcrypto.so event event_extra event_core)
|
||||
|
||||
5
android/third-party/Folly/build.gradle
vendored
5
android/third-party/Folly/build.gradle
vendored
@@ -9,7 +9,7 @@ android {
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
buildConfigField "boolean", "IS_INTERNAL_BUILD", 'true'
|
||||
ndk {
|
||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
abiFilters 'arm64-v8a', 'x86', 'armeabi-v7a', 'armeabi'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
@@ -34,6 +34,9 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation project(':glog')
|
||||
//implementation project(':libevent')
|
||||
implementation project(':doubleconversion')
|
||||
implementation project(':openssl')
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
4
android/third-party/LibEvent/ApplicationManifest.xml
vendored
Normal file
4
android/third-party/LibEvent/ApplicationManifest.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.libevent">
|
||||
</manifest>
|
||||
37
android/third-party/LibEvent/CMakeLists.txt
vendored
Normal file
37
android/third-party/LibEvent/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
cmake_minimum_required (VERSION 3.6.0)
|
||||
|
||||
PROJECT(libevent C)
|
||||
enable_language(C)
|
||||
set(PACKAGE_NAME libevent)
|
||||
set(LIBEVENT_DIR libevent-release-2.1.8-stable)
|
||||
list(APPEND DIR_LIST ${LIBEVENT_DIR}/)
|
||||
list(APPEND DIR_LIST ${LIBEVENT_DIR}/include)
|
||||
include_directories(${DIR_LIST})
|
||||
list(APPEND SRCFILES ${LIBEVENT_DIR}/event.c
|
||||
${LIBEVENT_DIR}/buffer.c
|
||||
${LIBEVENT_DIR}/bufferevent.c
|
||||
${LIBEVENT_DIR}/bufferevent_filter.c
|
||||
${LIBEVENT_DIR}/bufferevent_ratelim.c
|
||||
${LIBEVENT_DIR}/bufferevent_sock.c
|
||||
${LIBEVENT_DIR}/epoll.c
|
||||
${LIBEVENT_DIR}/epoll_sub.c
|
||||
${LIBEVENT_DIR}/evdns.c
|
||||
${LIBEVENT_DIR}/event_tagging.c
|
||||
${LIBEVENT_DIR}/evmap.c
|
||||
${LIBEVENT_DIR}/evrpc.c
|
||||
${LIBEVENT_DIR}/evthread.c
|
||||
${LIBEVENT_DIR}/evthread_pthread.c
|
||||
${LIBEVENT_DIR}/evutil.c
|
||||
${LIBEVENT_DIR}/evutil_rand.c
|
||||
${LIBEVENT_DIR}/http.c
|
||||
${LIBEVENT_DIR}/listener.c
|
||||
${LIBEVENT_DIR}/log.c
|
||||
${LIBEVENT_DIR}/poll.c
|
||||
${LIBEVENT_DIR}/select.c
|
||||
${LIBEVENT_DIR}/signal.c
|
||||
${LIBEVENT_DIR}/strlcpy.c
|
||||
)
|
||||
|
||||
add_library(${PACKAGE_NAME} SHARED ${SRCFILES})
|
||||
install(TARGETS ${PACKAGE_NAME} DESTINATION ./build/)
|
||||
target_link_libraries(${PACKAGE_NAME})
|
||||
33
android/third-party/LibEvent/build.gradle
vendored
Normal file
33
android/third-party/LibEvent/build.gradle
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.compileSdkVersion
|
||||
buildToolsVersion rootProject.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.minSdkVersion
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'x86', 'armeabi-v7a', 'armeabi'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DANDROID_TOOLCHAIN=clang'
|
||||
}
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile './ApplicationManifest.xml'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path 'libevent-release-2.1.9/CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
365
android/third-party/LibEvent/event-config.h
vendored
Normal file
365
android/third-party/LibEvent/event-config.h
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
/* event2/event-config.h
|
||||
*
|
||||
* This file was generated by autoconf when libevent was built, and post-
|
||||
* processed by Libevent so that its macros would have a uniform prefix.
|
||||
*
|
||||
* DO NOT EDIT THIS FILE.
|
||||
*
|
||||
* Do not rely on macros in this file existing in later versions.
|
||||
*/
|
||||
#ifndef EVENT_CONFIG_H__
|
||||
#define EVENT_CONFIG_H__
|
||||
/* config.h. Generated by configure. */
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define if libevent should not allow replacing the mm functions */
|
||||
/* #undef EVENT__DISABLE_MM_REPLACEMENT */
|
||||
|
||||
/* Define if libevent should not be compiled with thread support */
|
||||
/* #undef EVENT__DISABLE_THREAD_SUPPORT */
|
||||
|
||||
/* Define if clock_gettime is available in libc */
|
||||
/* #undef _EVENT_DNS_USE_CPU_CLOCK_FOR_ID */
|
||||
|
||||
/* Define is no secure id variant is available */
|
||||
/* #define _EVENT_DNS_USE_GETTIMEOFDAY_FOR_ID 1 */
|
||||
#define EVENT_DNS_USE_FTIME_FOR_ID_ 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
/* #undef EVENT__HAVE_ARPA_INET_H */
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
/* #undef EVENT__HAVE_CLOCK_GETTIME */
|
||||
|
||||
/* Define if /dev/poll is available */
|
||||
/* #undef EVENT__HAVE_DEVPOLL */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
/* #undef EVENT__HAVE_DLFCN_H */
|
||||
|
||||
/* Define if your system supports the epoll system calls */
|
||||
/* #undef EVENT__HAVE_EPOLL */
|
||||
|
||||
/* Define to 1 if you have the `epoll_ctl' function. */
|
||||
/* #undef EVENT__HAVE_EPOLL_CTL */
|
||||
|
||||
/* Define to 1 if you have the `eventfd' function. */
|
||||
/* #undef EVENT__HAVE_EVENTFD */
|
||||
|
||||
/* Define if your system supports event ports */
|
||||
/* #undef EVENT__HAVE_EVENT_PORTS */
|
||||
|
||||
/* Define to 1 if you have the `fcntl' function. */
|
||||
/* #undef EVENT__HAVE_FCNTL */
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define EVENT__HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#define EVENT__HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getnameinfo' function. */
|
||||
#define EVENT__HAVE_GETNAMEINFO 1
|
||||
|
||||
/* Define to 1 if you have the `getprotobynumber' function. */
|
||||
#define EVENT__HAVE_GETPROTOBYNUMBER 1
|
||||
|
||||
/* Define to 1 if you have the `getservbyname' function. */
|
||||
#define EVENT__HAVE_GETSERVBYNAME 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
/* #define EVENT__HAVE_GETTIMEOFDAY 1 */
|
||||
|
||||
/* Define to 1 if you have the `inet_ntop' function. */
|
||||
/* #undef EVENT__HAVE_INET_NTOP */
|
||||
|
||||
/* Define to 1 if you have the `inet_pton' function. */
|
||||
/* #undef EVENT__HAVE_INET_PTON */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
/* #define EVENT__HAVE_INTTYPES_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
/* #undef EVENT__HAVE_KQUEUE */
|
||||
|
||||
/* Define if the system has zlib */
|
||||
/* #undef EVENT__HAVE_LIBZ */
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define EVENT__HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
/* #undef EVENT__HAVE_MMAP */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in6.h> header file. */
|
||||
/* #undef EVENT__HAVE_NETINET_IN6_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
/* #undef EVENT__HAVE_NETINET_IN_H */
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
/* #undef EVENT__HAVE_PIPE */
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
/* #undef EVENT__HAVE_POLL */
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
/* #undef EVENT__HAVE_POLL_H */
|
||||
|
||||
/* Define to 1 if you have the `port_create' function. */
|
||||
/* #undef EVENT__HAVE_PORT_CREATE */
|
||||
|
||||
/* Define to 1 if you have the <port.h> header file. */
|
||||
/* #undef EVENT__HAVE_PORT_H */
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
/* #undef EVENT__HAVE_PTHREAD */
|
||||
|
||||
/* Define if we have pthreads on this system */
|
||||
/* #undef EVENT__HAVE_PTHREADS */
|
||||
|
||||
/* Define to 1 if the system has the type `sa_family_t'. */
|
||||
/* #undef EVENT__HAVE_SA_FAMILY_T */
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
/* #undef EVENT__HAVE_SELECT */
|
||||
|
||||
/* Define to 1 if you have the `sendfile' function. */
|
||||
/* #undef EVENT__HAVE_SENDFILE */
|
||||
|
||||
/* Define if F_SETFD is defined in <fcntl.h> */
|
||||
/* #undef EVENT__HAVE_SETFD */
|
||||
|
||||
/* Define to 1 if you have the `sigaction' function. */
|
||||
/* #undef EVENT__HAVE_SIGACTION */
|
||||
|
||||
/* Define to 1 if you have the `signal' function. */
|
||||
#define EVENT__HAVE_SIGNAL 1
|
||||
|
||||
/* Define to 1 if you have the `splice' function. */
|
||||
/* #undef EVENT__HAVE_SPLICE */
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#define EVENT__HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#define EVENT__HAVE_STDDEF_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
/* #define EVENT__HAVE_STDINT_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define EVENT__HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define EVENT__HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define EVENT__HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
/* #undef EVENT__HAVE_STRLCPY */
|
||||
|
||||
/* Define to 1 if you have the `strsep' function. */
|
||||
/* #undef EVENT__HAVE_STRSEP */
|
||||
|
||||
/* Define to 1 if you have the `strtok_r' function. */
|
||||
/* #undef EVENT__HAVE_STRTOK_R */
|
||||
|
||||
/* Define to 1 if you have the `strtoll' function. */
|
||||
/* #define EVENT__HAVE_STRTOLL 1 */
|
||||
|
||||
#define EVENT__HAVE_STRUCT_ADDRINFO 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct in6_addr'. */
|
||||
#define EVENT__HAVE_STRUCT_IN6_ADDR 1
|
||||
|
||||
/* Define to 1 if `s6_addr16' is member of `struct in6_addr'. */
|
||||
#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR16 1
|
||||
|
||||
/* Define to 1 if `s6_addr32' is member of `struct in6_addr'. */
|
||||
#define EVENT__HAVE_STRUCT_IN6_ADDR_S6_ADDR32 1
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_in6'. */
|
||||
#define EVENT__HAVE_STRUCT_SOCKADDR_IN6 1
|
||||
|
||||
/* Define to 1 if `sin6_len' is member of `struct sockaddr_in6'. */
|
||||
/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN */
|
||||
|
||||
/* Define to 1 if `sin_len' is member of `struct sockaddr_in'. */
|
||||
/* #undef EVENT__HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
||||
|
||||
/* Define to 1 if the system has the type `struct sockaddr_storage'. */
|
||||
#define EVENT__HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
|
||||
/* Define to 1 if you have the <sys/devpoll.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_DEVPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/epoll.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_EPOLL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/eventfd.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_EVENTFD_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/event.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_EVENT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_IOCTL_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_MMAN_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
/* #define EVENT__HAVE_SYS_PARAM_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <sys/queue.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_QUEUE_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/select.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_SELECT_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/sendfile.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_SENDFILE_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_SOCKET_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define EVENT__HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
/* #define EVENT__HAVE_SYS_TIME_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define EVENT__HAVE_SYS_TYPES_H 0
|
||||
|
||||
/* Define to 1 if you have the <sys/uio.h> header file. */
|
||||
/* #undef EVENT__HAVE_SYS_UIO_H */
|
||||
|
||||
/* Define if TAILQ_FOREACH is defined in <sys/queue.h> */
|
||||
/* #undef EVENT__HAVE_TAILQFOREACH */
|
||||
|
||||
/* Define if timeradd is defined in <sys/time.h> */
|
||||
/* #undef EVENT__HAVE_TIMERADD */
|
||||
|
||||
/* Define if timerclear is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERCLEAR 1
|
||||
|
||||
/* Define if timercmp is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERCMP 1
|
||||
|
||||
/* Define if timerisset is defined in <sys/time.h> */
|
||||
#define EVENT__HAVE_TIMERISSET 1
|
||||
|
||||
/* Define to 1 if the system has the type `uint16_t'. */
|
||||
/* #define EVENT__HAVE_UINT16_T 1 */
|
||||
|
||||
/* Define to 1 if the system has the type `uint32_t'. */
|
||||
/* #define EVENT__HAVE_UINT32_T 1 */
|
||||
|
||||
/* Define to 1 if the system has the type `uint64_t'. */
|
||||
/* #define EVENT__HAVE_UINT64_T 1 */
|
||||
|
||||
/* Define to 1 if the system has the type `uint8_t'. */
|
||||
/* #define EVENT__HAVE_UINT8_T 1 */
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
/* #define EVENT__HAVE_UNISTD_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
/* #undef EVENT__HAVE_VASPRINTF */
|
||||
|
||||
/* Define if kqueue works correctly with pipes */
|
||||
/* #undef EVENT__HAVE_WORKING_KQUEUE */
|
||||
|
||||
/* Numeric representation of the version */
|
||||
#define EVENT__NUMERIC_VERSION 0x02020001
|
||||
|
||||
/* Name of package */
|
||||
#define EVENT__PACKAGE "libevent"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define EVENT__PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define EVENT__PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define EVENT__PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define EVENT__PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define EVENT__PACKAGE_VERSION ""
|
||||
|
||||
/* Define to necessary symbol if this constant uses a non-standard name on
|
||||
your system. */
|
||||
/* #undef EVENT__PTHREAD_CREATE_JOINABLE */
|
||||
|
||||
/* The size of a `int', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_INT 4
|
||||
|
||||
/* The size of a `long', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_LONG 4
|
||||
|
||||
/* The size of a `long long', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of a `short', as computed by sizeof. */
|
||||
#define EVENT__SIZEOF_SHORT 2
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#ifdef _WIN64
|
||||
#define EVENT__SIZEOF_SIZE_T 8
|
||||
#else
|
||||
#define EVENT__SIZEOF_SIZE_T 4
|
||||
#endif
|
||||
|
||||
/* The size of `void *', as computed by sizeof. */
|
||||
#ifdef _WIN64
|
||||
#define EVENT__SIZEOF_VOID_P 8
|
||||
#else
|
||||
#define EVENT__SIZEOF_VOID_P 4
|
||||
#endif
|
||||
|
||||
/* The size of `time_t`, as computed by sizeof. */
|
||||
#ifdef _WIN64
|
||||
#define EVENT__SIZEOF_TIME_T 8
|
||||
#else
|
||||
#define EVENT__SIZEOF_TIME_T 4
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define EVENT__STDC_HEADERS 1
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#define EVENT__TIME_WITH_SYS_TIME 1
|
||||
|
||||
/* Version number of package */
|
||||
#define EVENT__VERSION "2.2.0-alpha-dev"
|
||||
|
||||
/* Define to appropriate substitue if compiler doesnt have __func__ */
|
||||
#define EVENT____func__ __FUNCTION__
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef _EVENT___cplusplus
|
||||
#define EVENT__inline __inline
|
||||
#endif
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef EVENT__pid_t
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
#undef EVENT__size_t
|
||||
|
||||
/* Define to unsigned int if you dont have it */
|
||||
#define EVENT__socklen_t unsigned int
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#define EVENT__ssize_t int
|
||||
//SSIZE_T
|
||||
|
||||
#endif
|
||||
4
android/third-party/OpenSSL/ApplicationManifest.xml
vendored
Normal file
4
android/third-party/OpenSSL/ApplicationManifest.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.openssl">
|
||||
</manifest>
|
||||
35
android/third-party/OpenSSL/build.gradle
vendored
Normal file
35
android/third-party/OpenSSL/build.gradle
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.compileSdkVersion
|
||||
buildToolsVersion rootProject.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.minSdkVersion
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'x86', 'armeabi-v7a', 'armeabi'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "NDK_APPLICATION_MK:=$projectDir/jni/Application.mk",
|
||||
"NDK_TOOLCHAIN_VERSION:=clang"
|
||||
cppFlags "-std=c++11"
|
||||
}
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path "$projectDir/jni/Android.mk"
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile './ApplicationManifest.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
android/third-party/OpenSSL/libs/arm64-v8a/libcrypto.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/arm64-v8a/libcrypto.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/arm64-v8a/libssl.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/arm64-v8a/libssl.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/arm64-v8a/openssl
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/arm64-v8a/openssl
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/arm64-v8a/ssltest
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/arm64-v8a/ssltest
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/libcrypto.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/libcrypto.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/libssl.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/libssl.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/openssl
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/openssl
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/ssltest
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi-v7a/ssltest
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi/libcrypto.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi/libcrypto.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi/libssl.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi/libssl.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi/openssl
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi/openssl
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/armeabi/ssltest
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/armeabi/ssltest
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/x86/libcrypto.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/x86/libcrypto.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/x86/libssl.so
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/x86/libssl.so
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/x86/openssl
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/x86/openssl
vendored
Executable file
Binary file not shown.
BIN
android/third-party/OpenSSL/libs/x86/ssltest
vendored
Executable file
BIN
android/third-party/OpenSSL/libs/x86/ssltest
vendored
Executable file
Binary file not shown.
4
android/third-party/RSocket/ApplicationManifest.xml
vendored
Normal file
4
android/third-party/RSocket/ApplicationManifest.xml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.rsocket">
|
||||
</manifest>
|
||||
92
android/third-party/RSocket/CMakeLists.txt
vendored
Normal file
92
android/third-party/RSocket/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
cmake_minimum_required (VERSION 3.6.0)
|
||||
|
||||
PROJECT(rsocket CXX)
|
||||
set(PACKAGE_NAME rsocket)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(third_party_ndk ${PROJECT_SOURCE_DIR}/../)
|
||||
set(libfolly_DIR ${third_party_ndk}/folly/)
|
||||
set(glog_DIR ${third_party_ndk}/glog)
|
||||
set(BOOST_DIR ${third_party_ndk}/boost/boost_1_63_0/)
|
||||
set(LIBEVENT_DIR ${third_party_ndk}/LibEvent/libevent-release-2.1.9/)
|
||||
set(DOUBLECONVERSION_DIR ${third_party_ndk}/double-conversion/double-conversion-3.0.0/)
|
||||
set(OPENSSL_DIR ${third_party_ndk}/OpenSSL/openssl-android-1.0.0/)
|
||||
|
||||
set(RSOCKET_ROOT_DIR ${PROJECT_SOURCE_DIR}/rsocket-cpp-0.10.1)
|
||||
set(RSOCKET_DIR ${PROJECT_SOURCE_DIR}/rsocket-cpp-0.10.1/rsocket)
|
||||
|
||||
list(APPEND dir_list ${RSOCKET_ROOT_DIR}/)
|
||||
list(APPEND dir_list ${RSOCKET_DIR}/)
|
||||
list(APPEND dir_list ${RSOCKET_DIR}/framing)
|
||||
list(APPEND dir_list ${RSOCKET_DIR}/internal)
|
||||
list(APPEND dir_list ${RSOCKET_DIR}/statemachine)
|
||||
list(APPEND dir_list ${RSOCKET_DIR}/transports)
|
||||
list(APPEND dir_list ${RSOCKET_DIR}/transports/tcp)
|
||||
list(APPEND dir_list ${RSOCKET_ROOT_DIR}/yarpl/flowable)
|
||||
list(APPEND dir_list ${RSOCKET_ROOT_DIR}/yarpl/observable)
|
||||
list(APPEND dir_list ${RSOCKET_ROOT_DIR}/yarpl/utils)
|
||||
|
||||
file(GLOB SRC_FILES ${RSOCKET_DIR}/*.cpp
|
||||
${RSOCKET_DIR}/internal/*.cpp
|
||||
${RSOCKET_DIR}/framing/*.cpp
|
||||
${RSOCKET_DIR}/statemachine/*.cpp
|
||||
${RSOCKET_DIR}/transports/*.cpp
|
||||
${RSOCKET_DIR}/transports/tcp/*.cpp
|
||||
${RSOCKET_ROOT_DIR}/yarpl/observable/*.cpp
|
||||
${RSOCKET_ROOT_DIR}/yarpl/flowable/*.cpp
|
||||
${RSOCKET_ROOT_DIR}/yarpl/utils/*.cpp
|
||||
)
|
||||
|
||||
include_directories(${dir_list})
|
||||
|
||||
add_compile_options(
|
||||
-DFOLLY_HAVE_CLOCK_GETTIME=1
|
||||
-DFOLLY_HAVE_PTHREAD=1
|
||||
-DFOLLY_NO_CONFIG=1
|
||||
-DFOLLY_HAVE_MEMRCHR
|
||||
-DFOLLY_MOBILE=1
|
||||
-DFOLLY_USE_LIBCPP=1
|
||||
-DFOLLY_HAVE_LIBJEMALLOC=0
|
||||
-DFOLLY_HAVE_PREADV=0
|
||||
-frtti
|
||||
-fexceptions
|
||||
-Wno-error
|
||||
-Wno-unused-local-typedefs
|
||||
-Wno-unused-variable
|
||||
-Wno-sign-compare
|
||||
-Wno-comment
|
||||
-Wno-return-type
|
||||
-Wno-tautological-constant-compare
|
||||
)
|
||||
|
||||
add_library(${PACKAGE_NAME} SHARED ${SRC_FILES})
|
||||
|
||||
set(build_DIR ${CMAKE_SOURCE_DIR}/build)
|
||||
set(libfolly_build_DIR ${build_DIR}/libfolly/${ANDROID_ABI})
|
||||
|
||||
file(MAKE_DIRECTORY ${build_DIR})
|
||||
|
||||
add_subdirectory(${libfolly_DIR} ${libfolly_build_DIR})
|
||||
|
||||
target_include_directories(${PACKAGE_NAME} PRIVATE
|
||||
${libfolly_DIR}
|
||||
${BOOST_DIR}
|
||||
${BOOST_DIR}/../
|
||||
${LIBEVENT_DIR}/
|
||||
${LIBEVENT_DIR}/include/
|
||||
${LIBEVENT_DIR}/include/event2
|
||||
${OPENSSL_DIR}/jni/openssl-android/
|
||||
${OPENSSL_DIR}/jni/openssl-android/include
|
||||
${OPENSSL_DIR}/jni/openssl-android/include/openssl
|
||||
${glog_DIR}
|
||||
${glog_DIR}/../
|
||||
${glog_DIR}/glog-0.3.5/src/
|
||||
)
|
||||
|
||||
|
||||
set(OPENSSL_LINK_DIRECTORIES ${third_party_ndk}/OpenSSL/libs/${ANDROID_ABI}/)
|
||||
|
||||
find_path(OPENSSL_LIBRARY libssl.so HINTS ${OPENSSL_LINK_DIRECTORIES})
|
||||
|
||||
target_link_libraries(${PACKAGE_NAME} folly glog double-conversion log event ${OPENSSL_LINK_DIRECTORIES}/libssl.so ${OPENSSL_LINK_DIRECTORIES}/libcrypto.so)
|
||||
35
android/third-party/RSocket/build.gradle
vendored
Normal file
35
android/third-party/RSocket/build.gradle
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.compileSdkVersion
|
||||
buildToolsVersion rootProject.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.minSdkVersion
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'x86', 'armeabi-v7a'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DANDROID_TOOLCHAIN=clang'
|
||||
}
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile './ApplicationManifest.xml'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path './CMakeLists.txt'
|
||||
//'rsocket-cpp-0.10.0/CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
//'x86', 'x86_64', 'armeabi-v7a',
|
||||
1
android/third-party/glog/CMakeLists.txt
vendored
1
android/third-party/glog/CMakeLists.txt
vendored
@@ -13,7 +13,6 @@ list(APPEND dir_list ${glog_DIR}/src)
|
||||
list(APPEND dir_list ${glog_DIR}/glog)
|
||||
list(APPEND dir_list ${glog_DIR}/base)
|
||||
|
||||
message(STATUS "dir_list = " ${dir_list})
|
||||
include_directories(${dir_list})
|
||||
|
||||
add_compile_options(
|
||||
|
||||
15
build.gradle
15
build.gradle
@@ -16,7 +16,10 @@ buildscript {
|
||||
subprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,12 +52,12 @@ ext.deps = [
|
||||
jsr305 : 'com.google.code.findbugs:jsr305:3.0.1',
|
||||
inferAnnotations : 'com.facebook.infer.annotation:infer-annotation:0.11.2',
|
||||
// Litho
|
||||
lithoAnnotations : 'com.facebook.litho:litho-annotations:0.15.0',
|
||||
lithoCore : 'com.facebook.litho:litho-core:0.15.0',
|
||||
lithoWidget : 'com.facebook.litho:litho-widget:0.15.0',
|
||||
lithoProcessor : 'com.facebook.litho:litho-processor:0.15.0',
|
||||
lithoFresco : 'com.facebook.litho:litho-fresco:0.15.0',
|
||||
lithoTesting : 'com.facebook.litho:litho-testing:0.15.0',
|
||||
lithoAnnotations : 'com.facebook.litho:litho-annotations:0.15.1-SNAPSHOT',
|
||||
lithoCore : 'com.facebook.litho:litho-core:0.15.1-SNAPSHOT',
|
||||
lithoWidget : 'com.facebook.litho:litho-widget:0.15.1-SNAPSHOT',
|
||||
lithoProcessor : 'com.facebook.litho:litho-processor:0.15.1-SNAPSHOT',
|
||||
lithoFresco : 'com.facebook.litho:litho-fresco:0.15.1-SNAPSHOT',
|
||||
lithoTesting : 'com.facebook.litho:litho-testing:0.15.1-SNAPSHOT',
|
||||
// Debugging and testing
|
||||
guava : 'com.google.guava:guava:20.0',
|
||||
robolectric : 'org.robolectric:robolectric:3.0',
|
||||
|
||||
4
libs/fbjni/ApplicationManifest.xml
Normal file
4
libs/fbjni/ApplicationManifest.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.facebook.libfb">
|
||||
</manifest>
|
||||
81
libs/fbjni/BUCK
Normal file
81
libs/fbjni/BUCK
Normal file
@@ -0,0 +1,81 @@
|
||||
load("//build_defs:fb_xplat_cxx_library.bzl", "fb_xplat_cxx_library")
|
||||
load("@xplat//build_defs:fb_java_library.bzl", "fb_java_library")
|
||||
|
||||
ANNOTATIONS_SRCS = [
|
||||
"java/com/facebook/jni/annotations/*.java",
|
||||
]
|
||||
|
||||
fb_java_library(
|
||||
name = "java_annotations",
|
||||
srcs = glob(ANNOTATIONS_SRCS),
|
||||
required_for_source_only_abi = True,
|
||||
)
|
||||
|
||||
fb_java_library(
|
||||
name = "java",
|
||||
srcs = glob(
|
||||
["java/**/*.java"],
|
||||
exclude = ANNOTATIONS_SRCS,
|
||||
),
|
||||
required_for_source_only_abi = True,
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
"//libraries/soloader/java/com/facebook/soloader:soloader",
|
||||
"//third-party/java/jsr-305:jsr-305",
|
||||
],
|
||||
exported_deps = [
|
||||
":java_annotations",
|
||||
],
|
||||
)
|
||||
|
||||
fb_xplat_cxx_library(
|
||||
name = "fbjni",
|
||||
srcs = glob([
|
||||
"cxx/fbjni/**/*.cpp",
|
||||
]),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob([
|
||||
("cxx", "fbjni/**/*.h"),
|
||||
]),
|
||||
allow_jni_merging = True,
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-fno-omit-frame-pointer",
|
||||
"-frtti",
|
||||
"-ffunction-sections",
|
||||
],
|
||||
enable_static_variant = True,
|
||||
exported_platform_headers = [
|
||||
(
|
||||
"^(?!android-arm$).*$",
|
||||
subdir_glob([
|
||||
("cxx", "lyra/**/*.h"),
|
||||
]),
|
||||
),
|
||||
],
|
||||
fbandroid_deps = [
|
||||
"xplat//third-party/linker_lib:atomic",
|
||||
],
|
||||
platform_srcs = [
|
||||
(
|
||||
"^(?!android-arm$).*$",
|
||||
glob([
|
||||
"cxx/lyra/*.cpp",
|
||||
]),
|
||||
),
|
||||
],
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"libfbjni\"",
|
||||
],
|
||||
soname = "libfbjni.$(ext)",
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
"xplat//third-party/linker_lib:android",
|
||||
],
|
||||
exported_deps = [
|
||||
"xplat//third-party/linker_lib:log",
|
||||
"//native/jni-hack:jni-hack",
|
||||
],
|
||||
)
|
||||
46
libs/fbjni/CMakeLists.txt
Normal file
46
libs/fbjni/CMakeLists.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (c) 2014-present, Facebook, Inc.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.6.0)
|
||||
set(PACKAGE_NAME "sonarfb")
|
||||
project(${PACKAGE_NAME} CXX)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE on)
|
||||
|
||||
add_compile_options(
|
||||
-fno-omit-frame-pointer
|
||||
-fexceptions
|
||||
-O3
|
||||
-Wall
|
||||
-std=c++11
|
||||
-frtti
|
||||
-ffunction-sections
|
||||
-DDISABLE_CPUCAP
|
||||
-DDISABLE_XPLAT)
|
||||
|
||||
set(FBJNI_CXX ${PROJECT_SOURCE_DIR}/cxx)
|
||||
|
||||
list(APPEND FBJNI_HDRS ${FBJNI_CXX})
|
||||
list(APPEND FBJNI_HDRS ${FBJNI_CXX}/fbjni/)
|
||||
list(APPEND FBJNI_HDRS ${FBJNI_CXX}/fbjni/detail)
|
||||
list(APPEND FBJNI_HDRS ${FBJNI_CXX}/lyra)
|
||||
list(APPEND FBJNI_HDRS ${FBJNI_CXX}/../../jni-hack)
|
||||
|
||||
include_directories(${FBJNI_HDRS})
|
||||
|
||||
file(GLOB FBJNI_SRC
|
||||
${FBJNI_CXX}/fbjni/*.cpp
|
||||
${FBJNI_CXX}/fbjni/detail/*.cpp
|
||||
${FBJNI_CXX}/lyra/*.cpp
|
||||
)
|
||||
|
||||
add_library(${PACKAGE_NAME} SHARED
|
||||
${FBJNI_SRC})
|
||||
|
||||
target_include_directories(${PACKAGE_NAME} PRIVATE ${FBJNI_HDRS})
|
||||
|
||||
target_link_libraries(${PACKAGE_NAME} android log)
|
||||
@@ -7,9 +7,16 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.minSdkVersion
|
||||
targetSdkVersion rootProject.targetSdkVersion
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile './ApplicationManifest.xml'
|
||||
java {
|
||||
srcDir 'java'
|
||||
}
|
||||
}
|
||||
}
|
||||
ndk {
|
||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
abiFilters 'arm64-v8a', 'x86', 'armeabi-v7a'
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
@@ -20,7 +27,7 @@ android {
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path './src/main/cpp/CMakeLists.txt'
|
||||
path './CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,4 +37,5 @@ dependencies {
|
||||
compileOnly deps.jsr305
|
||||
compileOnly deps.inferAnnotations
|
||||
compileOnly 'com.facebook.litho:litho-annotations:0.15.0'
|
||||
implementation deps.soloader
|
||||
}
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2016-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <fb/fbjni/ByteBuffer.h>
|
||||
|
||||
#include <fbjni/ByteBuffer.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <fb/fbjni/References.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
@@ -22,6 +29,11 @@ local_ref<JByteBuffer> createEmpty() {
|
||||
}
|
||||
}
|
||||
|
||||
void JBuffer::rewind() const {
|
||||
static auto meth = javaClassStatic()->getMethod<alias_ref<JBuffer>()>("rewind");
|
||||
meth(self());
|
||||
}
|
||||
|
||||
local_ref<JByteBuffer> JByteBuffer::wrapBytes(uint8_t* data, size_t size) {
|
||||
// env->NewDirectByteBuffer requires that size is positive. Android's
|
||||
// dalvik returns an invalid result and Android's art aborts if size == 0.
|
||||
45
libs/fbjni/cxx/fbjni/ByteBuffer.h
Normal file
45
libs/fbjni/cxx/fbjni/ByteBuffer.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
class JBuffer : public JavaClass<JBuffer> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/nio/Buffer;";
|
||||
|
||||
void rewind() const;
|
||||
};
|
||||
|
||||
// JNI's NIO support has some awkward preconditions and error reporting. This
|
||||
// class provides much more user-friendly access.
|
||||
class JByteBuffer : public JavaClass<JByteBuffer, JBuffer> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/nio/ByteBuffer;";
|
||||
|
||||
static local_ref<JByteBuffer> wrapBytes(uint8_t* data, size_t size);
|
||||
|
||||
bool isDirect() const;
|
||||
|
||||
uint8_t* getDirectBytes() const;
|
||||
size_t getDirectSize() const;
|
||||
};
|
||||
|
||||
}}
|
||||
42
libs/fbjni/cxx/fbjni/Context.h
Normal file
42
libs/fbjni/cxx/fbjni/Context.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <fbjni/File.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
class AContext : public JavaClass<AContext> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Landroid/content/Context;";
|
||||
|
||||
// Define a method that calls into the represented Java class
|
||||
local_ref<JFile::javaobject> getCacheDir() {
|
||||
static const auto method = getClass()->getMethod<JFile::javaobject()>("getCacheDir");
|
||||
return method(self());
|
||||
}
|
||||
|
||||
local_ref<JFile::javaobject> getFilesDir() {
|
||||
static const auto method = getClass()->getMethod<JFile::javaobject()>("getFilesDir");
|
||||
return method(self());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
37
libs/fbjni/cxx/fbjni/File.h
Normal file
37
libs/fbjni/cxx/fbjni/File.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
class JFile : public JavaClass<JFile> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/io/File;";
|
||||
|
||||
// Define a method that calls into the represented Java class
|
||||
std::string getAbsolutePath() {
|
||||
static const auto method = getClass()->getMethod<jstring()>("getAbsolutePath");
|
||||
return method(self())->toStdString();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
66
libs/fbjni/cxx/fbjni/JThread.h
Normal file
66
libs/fbjni/cxx/fbjni/JThread.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <fbjni/NativeRunnable.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
class JThread : public JavaClass<JThread> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/lang/Thread;";
|
||||
|
||||
void start() {
|
||||
static const auto method = javaClassStatic()->getMethod<void()>("start");
|
||||
method(self());
|
||||
}
|
||||
|
||||
void join() {
|
||||
static const auto method = javaClassStatic()->getMethod<void()>("join");
|
||||
method(self());
|
||||
}
|
||||
|
||||
static local_ref<JThread> create(std::function<void()>&& runnable) {
|
||||
auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(runnable));
|
||||
return newInstance(static_ref_cast<JRunnable::javaobject>(jrunnable));
|
||||
}
|
||||
|
||||
static local_ref<JThread> create(std::function<void()>&& runnable, std::string&& name) {
|
||||
auto jrunnable = JNativeRunnable::newObjectCxxArgs(std::move(runnable));
|
||||
return newInstance(static_ref_cast<JRunnable::javaobject>(jrunnable), make_jstring(std::move(name)));
|
||||
}
|
||||
|
||||
static local_ref<JThread> getCurrent() {
|
||||
static const auto method = javaClassStatic()->getStaticMethod<local_ref<JThread>()>("currentThread");
|
||||
return method(javaClassStatic());
|
||||
}
|
||||
|
||||
int getPriority() {
|
||||
static const auto method = getClass()->getMethod<jint()>("getPriority");
|
||||
return method(self());
|
||||
}
|
||||
|
||||
void setPriority(int priority) {
|
||||
static const auto method = getClass()->getMethod<void(int)>("setPriority");
|
||||
method(self(), priority);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreClasses.h"
|
||||
#include "Hybrid.h"
|
||||
#include "Registration.h"
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
28
libs/fbjni/cxx/fbjni/OnLoad.cpp
Normal file
28
libs/fbjni/cxx/fbjni/OnLoad.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <fbjni/NativeRunnable.h>
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
return facebook::jni::initialize(vm, [] {
|
||||
HybridDataOnLoad();
|
||||
JNativeRunnable::OnLoad();
|
||||
ThreadScope::OnLoad();
|
||||
});
|
||||
}
|
||||
31
libs/fbjni/cxx/fbjni/ReadableByteChannel.cpp
Normal file
31
libs/fbjni/cxx/fbjni/ReadableByteChannel.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fbjni/ReadableByteChannel.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
int JReadableByteChannel::read(alias_ref<JByteBuffer> dest) const {
|
||||
if (!self()) {
|
||||
throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException");
|
||||
}
|
||||
static auto method = javaClassStatic()->getMethod<jint(alias_ref<JByteBuffer>)>("read");
|
||||
return method(self(), dest);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
32
libs/fbjni/cxx/fbjni/ReadableByteChannel.h
Normal file
32
libs/fbjni/cxx/fbjni/ReadableByteChannel.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <fbjni/ByteBuffer.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
class JReadableByteChannel : public JavaClass<JReadableByteChannel> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/nio/channels/ReadableByteChannel;";
|
||||
|
||||
int read(alias_ref<JByteBuffer> dest) const;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreClasses.h"
|
||||
@@ -18,13 +27,13 @@ struct JPrimitive : JavaClass<T> {
|
||||
using typename JavaClass<T>::javaobject;
|
||||
using JavaClass<T>::javaClassStatic;
|
||||
static local_ref<javaobject> valueOf(jprim val) {
|
||||
static auto cls = javaClassStatic();
|
||||
static auto method =
|
||||
static const auto cls = javaClassStatic();
|
||||
static const auto method =
|
||||
cls->template getStaticMethod<javaobject(jprim)>("valueOf");
|
||||
return method(cls, val);
|
||||
}
|
||||
jprim value() const {
|
||||
static auto method =
|
||||
static const auto method =
|
||||
javaClassStatic()->template getMethod<jprim()>(T::kValueMethod);
|
||||
return method(this->self());
|
||||
}
|
||||
@@ -56,6 +65,10 @@ DEFINE_BOXED_PRIMITIVE(double, Double)
|
||||
|
||||
#undef DEFINE_BOXED_PRIMITIVE
|
||||
|
||||
struct JVoid : public jni::JavaClass<JVoid> {
|
||||
static auto constexpr kJavaDescriptor = "Ljava/lang/Void;";
|
||||
};
|
||||
|
||||
inline local_ref<jobject> autobox(alias_ref<jobject> val) {
|
||||
return make_local(val);
|
||||
}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @file Common.h
|
||||
*
|
||||
* Defining the stuff that don't deserve headers of their own...
|
||||
@@ -16,9 +25,6 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
#include <fb/Environment.h>
|
||||
|
||||
#ifdef FBJNI_DEBUG_REFS
|
||||
# ifdef __ANDROID__
|
||||
# include <android/log.h>
|
||||
@@ -43,11 +49,11 @@
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
FBEXPORT void throwPendingJniExceptionAsCppException();
|
||||
FBEXPORT void throwCppExceptionIf(bool condition);
|
||||
void throwPendingJniExceptionAsCppException();
|
||||
void throwCppExceptionIf(bool condition);
|
||||
|
||||
[[noreturn]] FBEXPORT void throwNewJavaException(jthrowable);
|
||||
[[noreturn]] FBEXPORT void throwNewJavaException(const char* throwableName, const char* msg);
|
||||
[[noreturn]] void throwNewJavaException(jthrowable);
|
||||
[[noreturn]] void throwNewJavaException(const char* throwableName, const char* msg);
|
||||
template<typename... Args>
|
||||
[[noreturn]] void throwNewJavaException(const char* throwableName, const char* fmt, Args... args);
|
||||
|
||||
@@ -66,20 +72,10 @@ template<typename... Args>
|
||||
* unhelpful way (typically a segfault) while trying to handle an exception
|
||||
* which occurs later.
|
||||
*/
|
||||
FBEXPORT jint initialize(JavaVM*, std::function<void()>&&) noexcept;
|
||||
jint initialize(JavaVM*, std::function<void()>&&) noexcept;
|
||||
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
* Retrieve a pointer the JNI environment of the current thread.
|
||||
*
|
||||
* @pre The current thread must be attached to the VM
|
||||
*/
|
||||
inline JNIEnv* getEnv() noexcept {
|
||||
// TODO(T6594868) Benchmark against raw JNI access
|
||||
return Environment::current();
|
||||
}
|
||||
|
||||
// Define to get extremely verbose logging of references and to enable reference stats
|
||||
#ifdef FBJNI_DEBUG_REFS
|
||||
template<typename... Args>
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
@@ -22,15 +31,15 @@ namespace jni {
|
||||
// jobject /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept {
|
||||
return internal::getEnv()->IsSameObject(lhs.get(), rhs.get()) != JNI_FALSE;
|
||||
return Environment::current()->IsSameObject(lhs.get(), rhs.get()) != JNI_FALSE;
|
||||
}
|
||||
|
||||
inline local_ref<JClass> JObject::getClass() const noexcept {
|
||||
return adopt_local(internal::getEnv()->GetObjectClass(self()));
|
||||
return adopt_local(Environment::current()->GetObjectClass(self()));
|
||||
}
|
||||
|
||||
inline bool JObject::isInstanceOf(alias_ref<JClass> cls) const noexcept {
|
||||
return internal::getEnv()->IsInstanceOf(self(), cls.get()) != JNI_FALSE;
|
||||
return Environment::current()->IsInstanceOf(self(), cls.get()) != JNI_FALSE;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -49,7 +58,7 @@ inline void JObject::setFieldValue(JField<T> field, T value) noexcept {
|
||||
}
|
||||
|
||||
inline std::string JObject::toString() const {
|
||||
static auto method = findClassLocal("java/lang/Object")->getMethod<jstring()>("toString");
|
||||
static const auto method = findClassLocal("java/lang/Object")->getMethod<jstring()>("toString");
|
||||
|
||||
return method(self())->toStdString();
|
||||
}
|
||||
@@ -78,13 +87,13 @@ MonitorLock::MonitorLock() noexcept : owned_(nullptr) {}
|
||||
|
||||
MonitorLock::MonitorLock(alias_ref<JObject> object) noexcept
|
||||
: owned_(object) {
|
||||
internal::getEnv()->MonitorEnter(object.get());
|
||||
Environment::current()->MonitorEnter(object.get());
|
||||
}
|
||||
|
||||
void MonitorLock::reset() noexcept {
|
||||
if (owned_) {
|
||||
internal::getEnv()->MonitorExit(owned_.get());
|
||||
if (internal::getEnv()->ExceptionCheck()) {
|
||||
Environment::current()->MonitorExit(owned_.get());
|
||||
if (Environment::current()->ExceptionCheck()) {
|
||||
abort(); // Lock mismatch
|
||||
}
|
||||
owned_ = nullptr;
|
||||
@@ -127,7 +136,7 @@ namespace detail {
|
||||
template<typename JC, typename... Args>
|
||||
static local_ref<JC> newInstance(Args... args) {
|
||||
static auto cls = JC::javaClassStatic();
|
||||
static auto constructor = cls->template getConstructor<typename JC::javaobject(Args...)>();
|
||||
static const auto constructor = cls->template getConstructor<typename JC::javaobject(Args...)>();
|
||||
return cls->newObject(constructor, args...);
|
||||
}
|
||||
}
|
||||
@@ -155,17 +164,18 @@ struct NativeMethod {
|
||||
};
|
||||
|
||||
inline local_ref<JClass> JClass::getSuperclass() const noexcept {
|
||||
return adopt_local(internal::getEnv()->GetSuperclass(self()));
|
||||
return adopt_local(Environment::current()->GetSuperclass(self()));
|
||||
}
|
||||
|
||||
inline void JClass::registerNatives(std::initializer_list<NativeMethod> methods) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
|
||||
JNINativeMethod jnimethods[methods.size()];
|
||||
size_t i = 0;
|
||||
for (auto it = methods.begin(); it < methods.end(); ++it, ++i) {
|
||||
jnimethods[i].name = it->name;
|
||||
jnimethods[i].signature = it->descriptor.c_str();
|
||||
// The JNI struct members are unnecessarily non-const.
|
||||
jnimethods[i].name = const_cast<char*>(it->name);
|
||||
jnimethods[i].signature = const_cast<char*>(it->descriptor.c_str());
|
||||
jnimethods[i].fnPtr = reinterpret_cast<void*>(it->wrapper);
|
||||
}
|
||||
|
||||
@@ -174,8 +184,13 @@ inline void JClass::registerNatives(std::initializer_list<NativeMethod> methods)
|
||||
}
|
||||
|
||||
inline bool JClass::isAssignableFrom(alias_ref<JClass> other) const noexcept {
|
||||
const auto env = internal::getEnv();
|
||||
const auto result = env->IsAssignableFrom(self(), other.get());
|
||||
const auto env = Environment::current();
|
||||
// Ths method has behavior compatible with the
|
||||
// java.lang.Class#isAssignableFrom method. The order of the
|
||||
// arguments to the JNI IsAssignableFrom C function is "opposite"
|
||||
// from what some might expect, which makes this code look a little
|
||||
// odd, but it is correct.
|
||||
const auto result = env->IsAssignableFrom(other.get(), self());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -199,7 +214,7 @@ template<typename F>
|
||||
inline JMethod<F> JClass::getMethod(
|
||||
const char* name,
|
||||
const char* descriptor) const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
const auto method = env->GetMethodID(self(), name, descriptor);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!method);
|
||||
return JMethod<F>{method};
|
||||
@@ -214,7 +229,7 @@ template<typename F>
|
||||
inline JStaticMethod<F> JClass::getStaticMethod(
|
||||
const char* name,
|
||||
const char* descriptor) const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
const auto method = env->GetStaticMethodID(self(), name, descriptor);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!method);
|
||||
return JStaticMethod<F>{method};
|
||||
@@ -229,7 +244,7 @@ template<typename F>
|
||||
inline JNonvirtualMethod<F> JClass::getNonvirtualMethod(
|
||||
const char* name,
|
||||
const char* descriptor) const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
const auto method = env->GetMethodID(self(), name, descriptor);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!method);
|
||||
return JNonvirtualMethod<F>{method};
|
||||
@@ -245,7 +260,7 @@ template<typename T>
|
||||
inline JField<enable_if_t<IsJniScalar<T>(), T>> JClass::getField(
|
||||
const char* name,
|
||||
const char* descriptor) const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
auto field = env->GetFieldID(self(), name, descriptor);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!field);
|
||||
return JField<T>{field};
|
||||
@@ -261,7 +276,7 @@ template<typename T>
|
||||
inline JStaticField<enable_if_t<IsJniScalar<T>(), T>> JClass::getStaticField(
|
||||
const char* name,
|
||||
const char* descriptor) const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
auto field = env->GetStaticFieldID(self(), name, descriptor);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!field);
|
||||
return JStaticField<T>{field};
|
||||
@@ -286,7 +301,7 @@ template<typename R, typename... Args>
|
||||
inline local_ref<R> JClass::newObject(
|
||||
JConstructor<R(Args...)> constructor,
|
||||
Args... args) const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
auto object = env->NewObject(self(), constructor.getId(),
|
||||
detail::callToJni(
|
||||
detail::Convert<typename std::decay<Args>::type>::toCall(args))...);
|
||||
@@ -339,46 +354,11 @@ struct Convert<const char*> {
|
||||
};
|
||||
}
|
||||
|
||||
// JStackTrace //////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline auto JStackTraceElement::create(
|
||||
const std::string& declaringClass, const std::string& methodName, const std::string& file, int line)
|
||||
-> local_ref<javaobject> {
|
||||
return newInstance(declaringClass, methodName, file, line);
|
||||
}
|
||||
|
||||
inline std::string JStackTraceElement::getClassName() const {
|
||||
static auto meth = javaClassStatic()->getMethod<local_ref<JString>()>("getClassName");
|
||||
return meth(self())->toStdString();
|
||||
}
|
||||
|
||||
inline std::string JStackTraceElement::getMethodName() const {
|
||||
static auto meth = javaClassStatic()->getMethod<local_ref<JString>()>("getMethodName");
|
||||
return meth(self())->toStdString();
|
||||
}
|
||||
|
||||
inline std::string JStackTraceElement::getFileName() const {
|
||||
static auto meth = javaClassStatic()->getMethod<local_ref<JString>()>("getFileName");
|
||||
return meth(self())->toStdString();
|
||||
}
|
||||
|
||||
inline int JStackTraceElement::getLineNumber() const {
|
||||
static auto meth = javaClassStatic()->getMethod<jint()>("getLineNumber");
|
||||
return meth(self());
|
||||
}
|
||||
|
||||
// jthrowable //////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline local_ref<JThrowable> JThrowable::initCause(alias_ref<JThrowable> cause) {
|
||||
static auto meth = javaClassStatic()->getMethod<javaobject(javaobject)>("initCause");
|
||||
return meth(self(), cause.get());
|
||||
}
|
||||
|
||||
// jtypeArray //////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
inline size_t JArray::size() const noexcept {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
return env->GetArrayLength(self());
|
||||
}
|
||||
}
|
||||
@@ -438,8 +418,8 @@ std::string JArrayClass<T>::get_instantiated_base_name() {
|
||||
|
||||
template<typename T>
|
||||
auto JArrayClass<T>::newArray(size_t size) -> local_ref<javaobject> {
|
||||
static auto elementClass = findClassStatic(jtype_traits<T>::base_name().c_str());
|
||||
const auto env = internal::getEnv();
|
||||
static const auto elementClass = findClassStatic(jtype_traits<T>::base_name().c_str());
|
||||
const auto env = Environment::current();
|
||||
auto rawArray = env->NewObjectArray(size, elementClass.get(), nullptr);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!rawArray);
|
||||
return adopt_local(static_cast<javaobject>(rawArray));
|
||||
@@ -447,13 +427,13 @@ auto JArrayClass<T>::newArray(size_t size) -> local_ref<javaobject> {
|
||||
|
||||
template<typename T>
|
||||
inline void JArrayClass<T>::setElement(size_t idx, const T& value) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
env->SetObjectArrayElement(this->self(), idx, value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline local_ref<T> JArrayClass<T>::getElement(size_t idx) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
auto rawElement = env->GetObjectArrayElement(this->self(), idx);
|
||||
return adopt_local(static_cast<T>(rawElement));
|
||||
}
|
||||
@@ -463,6 +443,11 @@ inline detail::ElementProxy<JArrayClass<T>> JArrayClass<T>::operator[](size_t in
|
||||
return detail::ElementProxy<JArrayClass<T>>(this, index);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
local_ref<typename JArrayClass<T>::javaobject> adopt_local_array(jobjectArray ref) {
|
||||
return adopt_local(static_cast<typename JArrayClass<T>::javaobject>(ref));
|
||||
}
|
||||
|
||||
// jarray /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename JArrayType>
|
||||
@@ -537,7 +522,7 @@ class PinnedCriticalAlloc {
|
||||
T** elements,
|
||||
size_t* size,
|
||||
jboolean* isCopy) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
*elements = static_cast<T*>(env->GetPrimitiveArrayCritical(array.get(), isCopy));
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!elements);
|
||||
*size = array->size();
|
||||
@@ -548,7 +533,7 @@ class PinnedCriticalAlloc {
|
||||
jint start,
|
||||
jint size,
|
||||
jint mode) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
env->ReleasePrimitiveArrayCritical(array.get(), elements, mode);
|
||||
}
|
||||
};
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** @file CoreClasses.h
|
||||
@@ -16,14 +25,11 @@
|
||||
#include "References-forward.h"
|
||||
#include "Meta-forward.h"
|
||||
#include "TypeTraits.h"
|
||||
#include <sstream>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
@@ -39,7 +45,7 @@ class JObject;
|
||||
/// in a "static auto" variable, or a static global.
|
||||
///
|
||||
/// @return Returns a leaked global reference to the class
|
||||
FBEXPORT alias_ref<JClass> findClassStatic(const char* name);
|
||||
alias_ref<JClass> findClassStatic(const char* name);
|
||||
|
||||
/// Lookup a class by name. Note this functions returns a local reference,
|
||||
/// which means that it must not be stored in a static variable.
|
||||
@@ -48,12 +54,12 @@ FBEXPORT alias_ref<JClass> findClassStatic(const char* name);
|
||||
/// (like caching method ids).
|
||||
///
|
||||
/// @return Returns a global reference to the class
|
||||
FBEXPORT local_ref<JClass> findClassLocal(const char* name);
|
||||
local_ref<JClass> findClassLocal(const char* name);
|
||||
|
||||
/// Check to see if two references refer to the same object. Comparison with nullptr
|
||||
/// returns true if and only if compared to another nullptr. A weak reference that
|
||||
/// refers to a reclaimed object count as nullptr.
|
||||
FBEXPORT bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept;
|
||||
bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept;
|
||||
|
||||
// Together, these classes allow convenient use of any class with the fbjni
|
||||
// helpers. To use:
|
||||
@@ -72,7 +78,7 @@ FBEXPORT bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexc
|
||||
// constexpr static auto kJavaDescriptor = "Lcom/example/package/MyClass;";
|
||||
//
|
||||
// void foo() {
|
||||
// static auto method = javaClassStatic()->getMethod<void()>("foo");
|
||||
// static const auto method = javaClassStatic()->getMethod<void()>("foo");
|
||||
// method(self());
|
||||
// }
|
||||
//
|
||||
@@ -96,7 +102,7 @@ static local_ref<JC> newInstance(Args... args);
|
||||
|
||||
class MonitorLock;
|
||||
|
||||
class FBEXPORT JObject : detail::JObjectBase {
|
||||
class JObject : detail::JObjectBase {
|
||||
public:
|
||||
static constexpr auto kJavaDescriptor = "Ljava/lang/Object;";
|
||||
|
||||
@@ -192,7 +198,7 @@ struct JTypeFor<T, Base, void> {
|
||||
// jthrowable) to be used as javaobject. This should only be necessary for
|
||||
// built-in jni types and not user-defined ones.
|
||||
template <typename T, typename Base = JObject, typename JType = void>
|
||||
class FBEXPORT JavaClass : public Base {
|
||||
class JavaClass : public Base {
|
||||
using JObjType = typename detail::JTypeFor<T, Base, JType>;
|
||||
public:
|
||||
using _javaobject = typename JObjType::_javaobject;
|
||||
@@ -220,7 +226,7 @@ protected:
|
||||
/// Wrapper to provide functionality to jclass references
|
||||
struct NativeMethod;
|
||||
|
||||
class FBEXPORT JClass : public JavaClass<JClass, JObject, jclass> {
|
||||
class JClass : public JavaClass<JClass, JObject, jclass> {
|
||||
public:
|
||||
/// Java type descriptor
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/lang/Class;";
|
||||
@@ -325,19 +331,23 @@ private:
|
||||
void registerNatives(const char* name, std::initializer_list<NativeMethod> methods);
|
||||
|
||||
/// Wrapper to provide functionality to jstring references
|
||||
class FBEXPORT JString : public JavaClass<JString, JObject, jstring> {
|
||||
class JString : public JavaClass<JString, JObject, jstring> {
|
||||
public:
|
||||
/// Java type descriptor
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/lang/String;";
|
||||
|
||||
/// Convenience method to convert a jstring object to a std::string
|
||||
std::string toStdString() const;
|
||||
|
||||
/// Convenience method to convert a jstring object to a std::u16string
|
||||
std::u16string toU16String() const;
|
||||
};
|
||||
|
||||
/// Convenience functions to convert a std::string or const char* into a @ref local_ref to a
|
||||
/// jstring
|
||||
FBEXPORT local_ref<JString> make_jstring(const char* modifiedUtf8);
|
||||
FBEXPORT local_ref<JString> make_jstring(const std::string& modifiedUtf8);
|
||||
/// Convenience functions to convert a const char*, std::string, or std::u16string
|
||||
/// into a @ref local_ref to a jstring.
|
||||
local_ref<JString> make_jstring(const char* modifiedUtf8);
|
||||
local_ref<JString> make_jstring(const std::string& modifiedUtf8);
|
||||
local_ref<JString> make_jstring(const std::u16string& utf16);
|
||||
|
||||
namespace detail {
|
||||
template<typename Target>
|
||||
@@ -365,7 +375,7 @@ class ElementProxy {
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
class FBEXPORT JArray : public JavaClass<JArray, JObject, jarray> {
|
||||
class JArray : public JavaClass<JArray, JObject, jarray> {
|
||||
public:
|
||||
// This cannot be used in a scope that derives a descriptor (like in a method
|
||||
// signature). Use a more derived type instead (like JArrayInt or
|
||||
@@ -377,7 +387,7 @@ class FBEXPORT JArray : public JavaClass<JArray, JObject, jarray> {
|
||||
// This is used so that the JArrayClass<T> javaobject extends jni's
|
||||
// jobjectArray. This class should not be used directly. A general Object[]
|
||||
// should use JArrayClass<jobject>.
|
||||
class FBEXPORT JTypeArray : public JavaClass<JTypeArray, JArray, jobjectArray> {
|
||||
class JTypeArray : public JavaClass<JTypeArray, JArray, jobjectArray> {
|
||||
// This cannot be used in a scope that derives a descriptor (like in a method
|
||||
// signature).
|
||||
static constexpr const char* kJavaDescriptor = nullptr;
|
||||
@@ -427,36 +437,13 @@ template <typename T>
|
||||
using jtypeArray = typename JArrayClass<T>::javaobject;
|
||||
|
||||
template<typename T>
|
||||
local_ref<typename JArrayClass<T>::javaobject> adopt_local_array(jobjectArray ref) {
|
||||
return adopt_local(static_cast<typename JArrayClass<T>::javaobject>(ref));
|
||||
}
|
||||
local_ref<typename JArrayClass<T>::javaobject> adopt_local_array(jobjectArray ref);
|
||||
|
||||
template<typename Target>
|
||||
local_ref<typename Target::javaentry> adopt_local(detail::ElementProxy<Target> elementProxy) {
|
||||
return static_cast<local_ref<typename Target::javaentry>>(elementProxy);
|
||||
}
|
||||
|
||||
|
||||
struct FBEXPORT JStackTraceElement : JavaClass<JStackTraceElement> {
|
||||
static auto constexpr kJavaDescriptor = "Ljava/lang/StackTraceElement;";
|
||||
|
||||
static local_ref<javaobject> create(const std::string& declaringClass, const std::string& methodName, const std::string& file, int line);
|
||||
|
||||
std::string getClassName() const;
|
||||
std::string getMethodName() const;
|
||||
std::string getFileName() const;
|
||||
int getLineNumber() const;
|
||||
};
|
||||
|
||||
/// Wrapper to provide functionality to jthrowable references
|
||||
class FBEXPORT JThrowable : public JavaClass<JThrowable, JObject, jthrowable> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/lang/Throwable;";
|
||||
local_ref<JThrowable> initCause(alias_ref<JThrowable> cause);
|
||||
using JStackTrace = JArrayClass<JStackTraceElement::javaobject>;
|
||||
local_ref<JStackTrace> getStackTrace();
|
||||
};
|
||||
|
||||
template <typename T, typename PinAlloc>
|
||||
class PinnedPrimitiveArray;
|
||||
|
||||
@@ -468,7 +455,7 @@ template <typename T> class PinnedCriticalAlloc;
|
||||
/// This is an empty holder by itself. Construct a PinnedPrimitiveArray to actually interact with
|
||||
/// the elements of the array.
|
||||
template <typename JArrayType>
|
||||
class FBEXPORT JPrimitiveArray :
|
||||
class JPrimitiveArray :
|
||||
public JavaClass<JPrimitiveArray<JArrayType>, detail::JArray, JArrayType> {
|
||||
static_assert(is_jni_primitive_array<JArrayType>(), "");
|
||||
public:
|
||||
@@ -508,14 +495,14 @@ private:
|
||||
void releaseElements(T* elements, jint mode);
|
||||
};
|
||||
|
||||
FBEXPORT local_ref<jbooleanArray> make_boolean_array(jsize size);
|
||||
FBEXPORT local_ref<jbyteArray> make_byte_array(jsize size);
|
||||
FBEXPORT local_ref<jcharArray> make_char_array(jsize size);
|
||||
FBEXPORT local_ref<jshortArray> make_short_array(jsize size);
|
||||
FBEXPORT local_ref<jintArray> make_int_array(jsize size);
|
||||
FBEXPORT local_ref<jlongArray> make_long_array(jsize size);
|
||||
FBEXPORT local_ref<jfloatArray> make_float_array(jsize size);
|
||||
FBEXPORT local_ref<jdoubleArray> make_double_array(jsize size);
|
||||
local_ref<jbooleanArray> make_boolean_array(jsize size);
|
||||
local_ref<jbyteArray> make_byte_array(jsize size);
|
||||
local_ref<jcharArray> make_char_array(jsize size);
|
||||
local_ref<jshortArray> make_short_array(jsize size);
|
||||
local_ref<jintArray> make_int_array(jsize size);
|
||||
local_ref<jlongArray> make_long_array(jsize size);
|
||||
local_ref<jfloatArray> make_float_array(jsize size);
|
||||
local_ref<jdoubleArray> make_double_array(jsize size);
|
||||
|
||||
using JArrayBoolean = JPrimitiveArray<jbooleanArray>;
|
||||
using JArrayByte = JPrimitiveArray<jbyteArray>;
|
||||
@@ -577,6 +564,29 @@ class PinnedPrimitiveArray {
|
||||
friend class JPrimitiveArray<typename jtype_traits<T>::array_type>;
|
||||
};
|
||||
|
||||
struct JStackTraceElement : JavaClass<JStackTraceElement> {
|
||||
static auto constexpr kJavaDescriptor = "Ljava/lang/StackTraceElement;";
|
||||
|
||||
static local_ref<javaobject> create(const std::string& declaringClass, const std::string& methodName, const std::string& file, int line);
|
||||
|
||||
std::string getClassName() const;
|
||||
std::string getMethodName() const;
|
||||
std::string getFileName() const;
|
||||
int getLineNumber() const;
|
||||
};
|
||||
|
||||
/// Wrapper to provide functionality to jthrowable references
|
||||
class JThrowable : public JavaClass<JThrowable, JObject, jthrowable> {
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/lang/Throwable;";
|
||||
|
||||
using JStackTrace = JArrayClass<JStackTraceElement::javaobject>;
|
||||
|
||||
local_ref<JThrowable> initCause(alias_ref<JThrowable> cause);
|
||||
local_ref<JStackTrace> getStackTrace();
|
||||
void setStackTrace(alias_ref<JArrayClass<JStackTraceElement::javaobject>>);
|
||||
};
|
||||
|
||||
#pragma push_macro("PlainJniRefMap")
|
||||
#undef PlainJniRefMap
|
||||
#define PlainJniRefMap(rtype, jtype) \
|
||||
301
libs/fbjni/cxx/fbjni/detail/Environment.cpp
Normal file
301
libs/fbjni/cxx/fbjni/detail/Environment.cpp
Normal file
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include <functional>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
namespace {
|
||||
|
||||
JavaVM* g_vm = nullptr;
|
||||
|
||||
struct EnvironmentInitializer {
|
||||
EnvironmentInitializer(JavaVM* vm) {
|
||||
FBJNI_ASSERT(!g_vm);
|
||||
FBJNI_ASSERT(vm);
|
||||
g_vm = vm;
|
||||
}
|
||||
};
|
||||
|
||||
int getEnv(JNIEnv** env) {
|
||||
FBJNI_ASSERT(g_vm);
|
||||
// g_vm->GetEnv() might not clear the env* in failure cases.
|
||||
*env = nullptr;
|
||||
jint ret = g_vm->GetEnv((void**)env, JNI_VERSION_1_6);
|
||||
// Other possibilites are that JNI_VERSION_1_6 is invalid, or some
|
||||
// unknown return was received.
|
||||
FBJNI_ASSERT(ret == JNI_OK || ret == JNI_EDETACHED);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Some jni.h define the first arg to AttachCurrentThread as void**,
|
||||
// and some as JNIEnv**. This hack allows both to work.
|
||||
|
||||
template <typename>
|
||||
struct AttachTraits;
|
||||
|
||||
template <>
|
||||
struct AttachTraits<jint(JavaVM::*)(JNIEnv**, void*)> {
|
||||
using EnvType = JNIEnv*;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AttachTraits<jint(JavaVM::*)(void**, void*)> {
|
||||
using EnvType = void*;
|
||||
};
|
||||
|
||||
JNIEnv* attachCurrentThread() {
|
||||
JavaVMAttachArgs args{JNI_VERSION_1_6, nullptr, nullptr};
|
||||
using AttachEnvType =
|
||||
typename AttachTraits<decltype(&JavaVM::AttachCurrentThread)>::EnvType;
|
||||
AttachEnvType env;
|
||||
auto result = g_vm->AttachCurrentThread(&env, &args);
|
||||
FBJNI_ASSERT(result == JNI_OK);
|
||||
return reinterpret_cast<JNIEnv*>(env);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* static */
|
||||
void Environment::initialize(JavaVM* vm) {
|
||||
static EnvironmentInitializer init(vm);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
pthread_key_t makeKey() {
|
||||
pthread_key_t key;
|
||||
int ret = pthread_key_create(&key, nullptr);
|
||||
if (ret != 0) {
|
||||
FBJNI_LOGF("pthread_key_create failed: %d", ret);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
pthread_key_t getTLKey() {
|
||||
static pthread_key_t key = makeKey();
|
||||
return key;
|
||||
}
|
||||
|
||||
inline detail::TLData* getTLData(pthread_key_t key) {
|
||||
return reinterpret_cast<detail::TLData*>(pthread_getspecific(key));
|
||||
}
|
||||
|
||||
inline void setTLData(pthread_key_t key, detail::TLData* data) {
|
||||
int ret = pthread_setspecific(key, data);
|
||||
if (ret != 0) {
|
||||
(void) ret;
|
||||
FBJNI_LOGF("pthread_setspecific failed: %d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
// This returns non-nullptr iff the env was cached from java. So it
|
||||
// can return nullptr for a thread which has been registered.
|
||||
inline JNIEnv* cachedOrNull() {
|
||||
detail::TLData* pdata = getTLData(getTLKey());
|
||||
return (pdata ? pdata->env : nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This will return a cached env if there is one, or get one from JNI
|
||||
// if the thread has already been attached some other way. If it
|
||||
// returns nullptr, then the thread has never been registered, or the
|
||||
// VM has never been set up for fbjni.
|
||||
|
||||
JNIEnv* currentOrNull() {
|
||||
if (!g_vm) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
detail::TLData* pdata = getTLData(getTLKey());
|
||||
if (pdata && pdata->env) {
|
||||
return pdata->env;
|
||||
}
|
||||
|
||||
JNIEnv* env;
|
||||
if (getEnv(&env) != JNI_OK) {
|
||||
// If there's a ThreadScope on the stack, we should have gotten a
|
||||
// JNIEnv and not ended up here.
|
||||
FBJNI_ASSERT(!pdata || !pdata->attached);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
// To understand JniEnvCacher and ThreadScope, it is helpful to
|
||||
// realize that if a flagged JniEnvCacher is on the stack, then a
|
||||
// flagged ThreadScope cannot be after it. If a flagged ThreadCacher
|
||||
// is on the stack, then a JniEnvCacher *can* be after it. So,
|
||||
// ThreadScope's setup and teardown can both assume they are the
|
||||
// first/last interesting objects, but this is not true of
|
||||
// JniEnvCacher.
|
||||
|
||||
JniEnvCacher::JniEnvCacher(JNIEnv* env)
|
||||
: thisCached_(false)
|
||||
{
|
||||
FBJNI_ASSERT(env);
|
||||
|
||||
pthread_key_t key = getTLKey();
|
||||
detail::TLData* pdata = getTLData(key);
|
||||
if (pdata && pdata->env) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
pdata = &data_;
|
||||
setTLData(key, pdata);
|
||||
pdata->attached = false;
|
||||
} else {
|
||||
FBJNI_ASSERT(!pdata->env);
|
||||
}
|
||||
|
||||
pdata->env = env;
|
||||
|
||||
thisCached_ = true;
|
||||
}
|
||||
|
||||
JniEnvCacher::~JniEnvCacher() {
|
||||
if (!thisCached_) {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_key_t key = getTLKey();
|
||||
TLData* pdata = getTLData(key);
|
||||
FBJNI_ASSERT(pdata);
|
||||
FBJNI_ASSERT(pdata->env != nullptr);
|
||||
pdata->env = nullptr;
|
||||
if (!pdata->attached) {
|
||||
setTLData(key, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ThreadScope::ThreadScope()
|
||||
: thisAttached_(false)
|
||||
{
|
||||
if (g_vm == nullptr) {
|
||||
throw std::runtime_error("fbjni is uninitialized; no thread can be attached.");
|
||||
}
|
||||
|
||||
JNIEnv* env;
|
||||
|
||||
// Check if the thread is attached somehow.
|
||||
auto result = getEnv(&env);
|
||||
if (result == JNI_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, it appears there's no thread attached and no env is
|
||||
// cached, or we would have returned already. So there better not
|
||||
// be TLData.
|
||||
|
||||
pthread_key_t key = getTLKey();
|
||||
detail::TLData* pdata = getTLData(key);
|
||||
FBJNI_ASSERT(pdata == nullptr);
|
||||
setTLData(key, &data_);
|
||||
|
||||
attachCurrentThread();
|
||||
|
||||
data_.env = nullptr;
|
||||
data_.attached = true;
|
||||
|
||||
thisAttached_ = true;
|
||||
}
|
||||
|
||||
ThreadScope::~ThreadScope() {
|
||||
if (!thisAttached_) {
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_key_t key = getTLKey();
|
||||
detail::TLData* pdata = getTLData(key);
|
||||
FBJNI_ASSERT(pdata);
|
||||
FBJNI_ASSERT(pdata->env == nullptr);
|
||||
FBJNI_ASSERT(pdata->attached);
|
||||
FBJNI_ASSERT(g_vm);
|
||||
g_vm->DetachCurrentThread();
|
||||
setTLData(key, nullptr);
|
||||
}
|
||||
|
||||
/* static */
|
||||
JNIEnv* Environment::current() {
|
||||
FBJNI_ASSERT(g_vm);
|
||||
JNIEnv* env = detail::currentOrNull();
|
||||
if (env == nullptr) {
|
||||
throw std::runtime_error("Unable to retrieve jni environment. Is the thread attached?");
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
/* static */
|
||||
JNIEnv* Environment::ensureCurrentThreadIsAttached() {
|
||||
FBJNI_ASSERT(g_vm);
|
||||
JNIEnv* env = detail::currentOrNull();
|
||||
if (env == nullptr) {
|
||||
env = attachCurrentThread();
|
||||
FBJNI_ASSERT(env);
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct JThreadScopeSupport : JavaClass<JThreadScopeSupport> {
|
||||
static auto constexpr kJavaDescriptor = "Lcom/facebook/jni/ThreadScopeSupport;";
|
||||
|
||||
// These reinterpret_casts are a totally dangerous pattern. Don't use them. Use HybridData instead.
|
||||
static void runStdFunction(std::function<void()>&& func) {
|
||||
static const auto method = javaClassStatic()->getStaticMethod<void(jlong)>("runStdFunction");
|
||||
method(javaClassStatic(), reinterpret_cast<jlong>(&func));
|
||||
}
|
||||
|
||||
static void runStdFunctionImpl(alias_ref<JClass>, jlong ptr) {
|
||||
(*reinterpret_cast<std::function<void()>*>(ptr))();
|
||||
}
|
||||
|
||||
static void OnLoad() {
|
||||
// We need the javaClassStatic so that the class lookup is cached and that
|
||||
// runStdFunction can be called from a ThreadScope-attached thread.
|
||||
javaClassStatic()->registerNatives({
|
||||
makeNativeMethod("runStdFunctionImpl", runStdFunctionImpl),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* static */
|
||||
void ThreadScope::OnLoad() {
|
||||
// These classes are required for ScopeWithClassLoader. Ensure they are looked up when loading.
|
||||
JThreadScopeSupport::OnLoad();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void ThreadScope::WithClassLoader(std::function<void()>&& runnable) {
|
||||
if (cachedOrNull() == nullptr) {
|
||||
ThreadScope ts;
|
||||
JThreadScopeSupport::runStdFunction(std::move(runnable));
|
||||
} else {
|
||||
runnable();
|
||||
}
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -1,33 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <jni.h>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
// Keeps a thread-local reference to the current thread's JNIEnv.
|
||||
struct Environment {
|
||||
// May be null if this thread isn't attached to the JVM
|
||||
FBEXPORT static JNIEnv* current();
|
||||
// Throws a std::runtime_error if this thread isn't attached to the JVM
|
||||
// TODO(T6594868) Benchmark against raw JNI access
|
||||
static JNIEnv* current();
|
||||
static void initialize(JavaVM* vm);
|
||||
|
||||
// There are subtle issues with calling the next functions directly. It is
|
||||
// much better to always use a ThreadScope to manage attaching/detaching for
|
||||
// you.
|
||||
FBEXPORT static JNIEnv* ensureCurrentThreadIsAttached();
|
||||
FBEXPORT static void detachCurrentThread();
|
||||
static JNIEnv* ensureCurrentThreadIsAttached();
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// This will return null the thread isn't attached to the VM, or if
|
||||
// fbjni has never been initialized with a VM at all. You probably
|
||||
// shouldn't be using this.
|
||||
JNIEnv* currentOrNull();
|
||||
|
||||
/**
|
||||
* If there's thread-local data, it's a pointer to one of these. The
|
||||
* instance is a member of JniEnvCacher or ThreadScope, and lives on
|
||||
* the stack.
|
||||
*/
|
||||
struct TLData {
|
||||
// This is modified only by JniEnvCacher, and is guaranteed to be
|
||||
// valid if set, and refer to an env which originated from a JNI
|
||||
// call into C++.
|
||||
JNIEnv* env;
|
||||
// This is modified only by ThreadScope, and is set only if an
|
||||
// instance of ThreadScope which attached is on the stack.
|
||||
bool attached;
|
||||
};
|
||||
|
||||
/**
|
||||
* RAII object which manages a cached JNIEnv* value. A Value is only
|
||||
* cached if it is guaranteed safe, which means when C++ is called
|
||||
* from a registered fbjni function.
|
||||
*/
|
||||
class JniEnvCacher {
|
||||
public:
|
||||
JniEnvCacher(JNIEnv* env);
|
||||
JniEnvCacher(JniEnvCacher&) = delete;
|
||||
JniEnvCacher(JniEnvCacher&&) = default;
|
||||
JniEnvCacher& operator=(JniEnvCacher&) = delete;
|
||||
JniEnvCacher& operator=(JniEnvCacher&&) = delete;
|
||||
~JniEnvCacher();
|
||||
|
||||
private:
|
||||
// If this flag is set, then, this object needs to clear the cache.
|
||||
bool thisCached_;
|
||||
|
||||
// The thread local pointer may point here.
|
||||
detail::TLData data_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* RAII Object that attaches a thread to the JVM. Failing to detach from a thread before it
|
||||
* exits will cause a crash, as will calling Detach an extra time, and this guard class helps
|
||||
@@ -49,8 +103,11 @@ struct Environment {
|
||||
* class or instance to the new thread; this bypasses the need for the class loader.
|
||||
* (See http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html#attach_current_thread)
|
||||
* If you need access to the application's classes, you can use ThreadScope::WithClassLoader.
|
||||
* - If fbjni has never been initialized, there will be no JavaVM object to attach with.
|
||||
* In that case, a std::runtime_error will be thrown. This is only likely to happen in a
|
||||
* standalone C++ application, or if Environment::initialize is not used.
|
||||
*/
|
||||
class FBEXPORT ThreadScope {
|
||||
class ThreadScope {
|
||||
public:
|
||||
ThreadScope();
|
||||
ThreadScope(ThreadScope&) = delete;
|
||||
@@ -68,8 +125,14 @@ class FBEXPORT ThreadScope {
|
||||
static void WithClassLoader(std::function<void()>&& runnable);
|
||||
|
||||
static void OnLoad();
|
||||
|
||||
private:
|
||||
bool attachedWithThisScope_;
|
||||
// If this flag is set, then this object needs to detach.
|
||||
bool thisAttached_;
|
||||
|
||||
// The thread local pointer may point here.
|
||||
detail::TLData data_;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
400
libs/fbjni/cxx/fbjni/detail/Exceptions.cpp
Normal file
400
libs/fbjni/cxx/fbjni/detail/Exceptions.cpp
Normal file
@@ -0,0 +1,400 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "CoreClasses.h"
|
||||
#include "Log.h"
|
||||
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
#include <lyra/lyra.h>
|
||||
#include <lyra/lyra_exceptions.h>
|
||||
#endif
|
||||
|
||||
#include <alloca.h>
|
||||
#include <cstdlib>
|
||||
#include <ios>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
namespace {
|
||||
class JRuntimeException : public JavaClass<JRuntimeException, JThrowable> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Ljava/lang/RuntimeException;";
|
||||
|
||||
static local_ref<JRuntimeException> create(const char* str) {
|
||||
return newInstance(make_jstring(str));
|
||||
}
|
||||
|
||||
static local_ref<JRuntimeException> create() {
|
||||
return newInstance();
|
||||
}
|
||||
};
|
||||
|
||||
class JIOException : public JavaClass<JIOException, JThrowable> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Ljava/io/IOException;";
|
||||
|
||||
static local_ref<JIOException> create(const char* str) {
|
||||
return newInstance(make_jstring(str));
|
||||
}
|
||||
};
|
||||
|
||||
class JOutOfMemoryError : public JavaClass<JOutOfMemoryError, JThrowable> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Ljava/lang/OutOfMemoryError;";
|
||||
|
||||
static local_ref<JOutOfMemoryError> create(const char* str) {
|
||||
return newInstance(make_jstring(str));
|
||||
}
|
||||
};
|
||||
|
||||
class JArrayIndexOutOfBoundsException : public JavaClass<JArrayIndexOutOfBoundsException, JThrowable> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Ljava/lang/ArrayIndexOutOfBoundsException;";
|
||||
|
||||
static local_ref<JArrayIndexOutOfBoundsException> create(const char* str) {
|
||||
return newInstance(make_jstring(str));
|
||||
}
|
||||
};
|
||||
|
||||
class JUnknownCppException : public JavaClass<JUnknownCppException, JThrowable> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/facebook/jni/UnknownCppException;";
|
||||
|
||||
static local_ref<JUnknownCppException> create() {
|
||||
return newInstance();
|
||||
}
|
||||
|
||||
static local_ref<JUnknownCppException> create(const char* str) {
|
||||
return newInstance(make_jstring(str));
|
||||
}
|
||||
};
|
||||
|
||||
class JCppSystemErrorException : public JavaClass<JCppSystemErrorException, JThrowable> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/facebook/jni/CppSystemErrorException;";
|
||||
|
||||
static local_ref<JCppSystemErrorException> create(const std::system_error& e) {
|
||||
return newInstance(make_jstring(e.what()), e.code().value());
|
||||
}
|
||||
};
|
||||
|
||||
// Exception throwing & translating functions //////////////////////////////////////////////////////
|
||||
|
||||
// Functions that throw Java exceptions
|
||||
|
||||
void setJavaExceptionAndAbortOnFailure(alias_ref<JThrowable> throwable) {
|
||||
auto env = Environment::current();
|
||||
if (throwable) {
|
||||
env->Throw(throwable.get());
|
||||
}
|
||||
if (env->ExceptionCheck() != JNI_TRUE) {
|
||||
FBJNI_LOGF("Failed to set Java exception");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Functions that throw C++ exceptions
|
||||
|
||||
// TODO(T6618159) Inject the c++ stack into the exception's stack trace. One
|
||||
// issue: when a java exception is created, it captures the full java stack
|
||||
// across jni boundaries. lyra will only capture the c++ stack to the jni
|
||||
// boundary. So, as we pass the java exception up to c++, we need to capture
|
||||
// the c++ stack and then insert it into the correct place in the java stack
|
||||
// trace. Then, as the exception propagates across the boundaries, we will
|
||||
// slowly fill in the c++ parts of the trace.
|
||||
void throwPendingJniExceptionAsCppException() {
|
||||
JNIEnv* env = Environment::current();
|
||||
if (env->ExceptionCheck() == JNI_FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto throwable = adopt_local(env->ExceptionOccurred());
|
||||
if (!throwable) {
|
||||
throw std::runtime_error("Unable to get pending JNI exception.");
|
||||
}
|
||||
env->ExceptionClear();
|
||||
|
||||
throw JniException(throwable);
|
||||
}
|
||||
|
||||
void throwCppExceptionIf(bool condition) {
|
||||
if (!condition) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto env = Environment::current();
|
||||
if (env->ExceptionCheck() == JNI_TRUE) {
|
||||
throwPendingJniExceptionAsCppException();
|
||||
return;
|
||||
}
|
||||
|
||||
throw JniException();
|
||||
}
|
||||
|
||||
void throwNewJavaException(jthrowable throwable) {
|
||||
throw JniException(wrap_alias(throwable));
|
||||
}
|
||||
|
||||
void throwNewJavaException(const char* throwableName, const char* msg) {
|
||||
// If anything of the fbjni calls fail, an exception of a suitable
|
||||
// form will be thrown, which is what we want.
|
||||
auto throwableClass = findClassLocal(throwableName);
|
||||
auto throwable = throwableClass->newObject(
|
||||
throwableClass->getConstructor<jthrowable(jstring)>(),
|
||||
make_jstring(msg).release());
|
||||
throwNewJavaException(throwable.get());
|
||||
}
|
||||
|
||||
// jthrowable //////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
local_ref<JThrowable> JThrowable::initCause(alias_ref<JThrowable> cause) {
|
||||
static auto meth = javaClassStatic()->getMethod<javaobject(alias_ref<javaobject>)>("initCause");
|
||||
return meth(self(), cause);
|
||||
}
|
||||
|
||||
auto JThrowable::getStackTrace() -> local_ref<JStackTrace> {
|
||||
static auto meth = javaClassStatic()->getMethod<JStackTrace::javaobject()>("getStackTrace");
|
||||
return meth(self());
|
||||
}
|
||||
|
||||
void JThrowable::setStackTrace(alias_ref<JStackTrace> stack) {
|
||||
static auto meth = javaClassStatic()->getMethod<void(alias_ref<JStackTrace>)>("setStackTrace");
|
||||
return meth(self(), stack);
|
||||
}
|
||||
|
||||
auto JStackTraceElement::create(
|
||||
const std::string& declaringClass, const std::string& methodName, const std::string& file, int line)
|
||||
-> local_ref<javaobject> {
|
||||
return newInstance(declaringClass, methodName, file, line);
|
||||
}
|
||||
|
||||
std::string JStackTraceElement::getClassName() const {
|
||||
static auto meth = javaClassStatic()->getMethod<local_ref<JString>()>("getClassName");
|
||||
return meth(self())->toStdString();
|
||||
}
|
||||
|
||||
std::string JStackTraceElement::getMethodName() const {
|
||||
static auto meth = javaClassStatic()->getMethod<local_ref<JString>()>("getMethodName");
|
||||
return meth(self())->toStdString();
|
||||
}
|
||||
|
||||
std::string JStackTraceElement::getFileName() const {
|
||||
static auto meth = javaClassStatic()->getMethod<local_ref<JString>()>("getFileName");
|
||||
return meth(self())->toStdString();
|
||||
}
|
||||
|
||||
int JStackTraceElement::getLineNumber() const {
|
||||
static auto meth = javaClassStatic()->getMethod<jint()>("getLineNumber");
|
||||
return meth(self());
|
||||
}
|
||||
|
||||
// Translate C++ to Java Exception
|
||||
|
||||
namespace {
|
||||
|
||||
// For each exception in the chain of the exception_ptr argument, func
|
||||
// will be called with that exception (in reverse order, i.e. innermost first).
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
void denest(const std::function<void(std::exception_ptr)>& func, std::exception_ptr ptr) {
|
||||
FBJNI_ASSERT(ptr);
|
||||
try {
|
||||
std::rethrow_exception(ptr);
|
||||
} catch (const std::nested_exception& e) {
|
||||
denest(func, e.nested_ptr());
|
||||
} catch (...) {
|
||||
// ignored.
|
||||
}
|
||||
func(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
local_ref<JStackTraceElement> createJStackTraceElement(const lyra::StackTraceElement& cpp) {
|
||||
return JStackTraceElement::create(
|
||||
"|lyra|{" + cpp.libraryName() + "}", cpp.functionName(), cpp.buildId(), cpp.libraryOffset());
|
||||
}
|
||||
|
||||
void addCppStacktraceToJavaException(alias_ref<JThrowable> java, std::exception_ptr cpp) {
|
||||
auto cppStack = lyra::getStackTraceSymbols(
|
||||
(cpp == nullptr) ?
|
||||
lyra::getStackTrace()
|
||||
: lyra::getExceptionTrace(cpp));
|
||||
|
||||
auto javaStack = java->getStackTrace();
|
||||
auto newStack = JThrowable::JStackTrace::newArray(javaStack->size() + cppStack.size());
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; j < cppStack.size(); j++, i++) {
|
||||
(*newStack)[i] = createJStackTraceElement(cppStack[j]);
|
||||
}
|
||||
for (size_t j = 0; j < javaStack->size(); j++, i++) {
|
||||
(*newStack)[i] = (*javaStack)[j];
|
||||
}
|
||||
java->setStackTrace(newStack);
|
||||
}
|
||||
|
||||
local_ref<JThrowable> convertCppExceptionToJavaException(std::exception_ptr ptr) {
|
||||
FBJNI_ASSERT(ptr);
|
||||
local_ref<JThrowable> current;
|
||||
bool addCppStack = true;
|
||||
try {
|
||||
std::rethrow_exception(ptr);
|
||||
addCppStack = false;
|
||||
} catch (const JniException& ex) {
|
||||
current = ex.getThrowable();
|
||||
} catch (const std::ios_base::failure& ex) {
|
||||
current = JIOException::create(ex.what());
|
||||
} catch (const std::bad_alloc& ex) {
|
||||
current = JOutOfMemoryError::create(ex.what());
|
||||
} catch (const std::out_of_range& ex) {
|
||||
current = JArrayIndexOutOfBoundsException::create(ex.what());
|
||||
} catch (const std::system_error& ex) {
|
||||
current = JCppSystemErrorException::create(ex);
|
||||
} catch (const std::runtime_error& ex) {
|
||||
current = JRuntimeException::create(ex.what());
|
||||
} catch (const std::exception& ex) {
|
||||
current = JCppException::create(ex.what());
|
||||
} catch (const char* msg) {
|
||||
current = JUnknownCppException::create(msg);
|
||||
} catch (...) {
|
||||
current = JUnknownCppException::create();
|
||||
}
|
||||
|
||||
if (addCppStack) {
|
||||
addCppStacktraceToJavaException(current, ptr);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
#endif
|
||||
|
||||
local_ref<JThrowable> getJavaExceptionForCppBackTrace() {
|
||||
return getJavaExceptionForCppBackTrace(nullptr);
|
||||
}
|
||||
|
||||
local_ref<JThrowable> getJavaExceptionForCppBackTrace(const char* msg) {
|
||||
local_ref<JThrowable> current =
|
||||
msg ? JUnknownCppException::create(msg) : JUnknownCppException::create();
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
addCppStacktraceToJavaException(current, nullptr);
|
||||
#endif
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
local_ref<JThrowable> getJavaExceptionForCppException(std::exception_ptr ptr) {
|
||||
FBJNI_ASSERT(ptr);
|
||||
local_ref<JThrowable> previous;
|
||||
auto func = [&previous] (std::exception_ptr ptr) {
|
||||
auto current = convertCppExceptionToJavaException(ptr);
|
||||
if (previous) {
|
||||
current->initCause(previous);
|
||||
}
|
||||
previous = current;
|
||||
};
|
||||
denest(func, ptr);
|
||||
return previous;
|
||||
}
|
||||
#endif
|
||||
|
||||
void translatePendingCppExceptionToJavaException() {
|
||||
try {
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
auto exc = getJavaExceptionForCppException(std::current_exception());
|
||||
#else
|
||||
auto exc = JUnknownCppException::create();
|
||||
#endif
|
||||
setJavaExceptionAndAbortOnFailure(exc);
|
||||
} catch (...) {
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
FBJNI_LOGE(
|
||||
"Unexpected error in translatePendingCppExceptionToJavaException(): %s",
|
||||
lyra::toString(std::current_exception()).c_str());
|
||||
#else
|
||||
FBJNI_LOGE(
|
||||
"Unexpected error in translatePendingCppExceptionToJavaException()");
|
||||
#endif
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
// JniException ////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string JniException::kExceptionMessageFailure_ = "Unable to get exception message.";
|
||||
|
||||
JniException::JniException() : JniException(JRuntimeException::create()) { }
|
||||
|
||||
JniException::JniException(alias_ref<jthrowable> throwable) : isMessageExtracted_(false) {
|
||||
throwable_ = make_global(throwable);
|
||||
}
|
||||
|
||||
JniException::JniException(JniException &&rhs)
|
||||
: throwable_(std::move(rhs.throwable_)),
|
||||
what_(std::move(rhs.what_)),
|
||||
isMessageExtracted_(rhs.isMessageExtracted_) {
|
||||
}
|
||||
|
||||
JniException::JniException(const JniException &rhs)
|
||||
: what_(rhs.what_), isMessageExtracted_(rhs.isMessageExtracted_) {
|
||||
throwable_ = make_global(rhs.throwable_);
|
||||
}
|
||||
|
||||
JniException::~JniException() {
|
||||
try {
|
||||
ThreadScope ts;
|
||||
throwable_.reset();
|
||||
} catch (...) {
|
||||
FBJNI_LOGE("Exception in ~JniException()");
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
local_ref<JThrowable> JniException::getThrowable() const noexcept {
|
||||
return make_local(throwable_);
|
||||
}
|
||||
|
||||
// TODO 6900503: consider making this thread-safe.
|
||||
void JniException::populateWhat() const noexcept {
|
||||
try {
|
||||
ThreadScope ts;
|
||||
what_ = throwable_->toString();
|
||||
isMessageExtracted_ = true;
|
||||
} catch(...) {
|
||||
what_ = kExceptionMessageFailure_;
|
||||
}
|
||||
}
|
||||
|
||||
const char* JniException::what() const noexcept {
|
||||
if (!isMessageExtracted_) {
|
||||
populateWhat();
|
||||
}
|
||||
return what_.c_str();
|
||||
}
|
||||
|
||||
void JniException::setJavaException() const noexcept {
|
||||
setJavaExceptionAndAbortOnFailure(throwable_);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Exceptions.h
|
||||
*
|
||||
@@ -24,12 +33,15 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "References.h"
|
||||
#include "CoreClasses.h"
|
||||
|
||||
#if defined(__ANDROID__) && defined(__ARM_ARCH_5TE__) && !defined(FBJNI_NO_EXCEPTION_PTR)
|
||||
// ARMv5 NDK does not support exception_ptr so we cannot use that when building for it.
|
||||
#define FBJNI_NO_EXCEPTION_PTR
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
@@ -58,7 +70,7 @@ class JCppException : public JavaClass<JCppException, JThrowable> {
|
||||
*
|
||||
* Note: the what() method of this class is not thread-safe (t6900503).
|
||||
*/
|
||||
class FBEXPORT JniException : public std::exception {
|
||||
class JniException : public std::exception {
|
||||
public:
|
||||
JniException();
|
||||
~JniException();
|
||||
@@ -106,11 +118,23 @@ template<typename... Args>
|
||||
}
|
||||
|
||||
// Identifies any pending C++ exception and throws it as a Java exception. If the exception can't
|
||||
// be thrown, it aborts the program. This is a noexcept function at C++ level.
|
||||
FBEXPORT void translatePendingCppExceptionToJavaException() noexcept;
|
||||
// be thrown, it aborts the program.
|
||||
void translatePendingCppExceptionToJavaException();
|
||||
|
||||
#ifndef FBJNI_NO_EXCEPTION_PTR
|
||||
local_ref<JThrowable> getJavaExceptionForCppException(std::exception_ptr ptr);
|
||||
#endif
|
||||
|
||||
/***
|
||||
* The stack returned may include build ids. It may be beneficial to
|
||||
* call lyra::setLibraryIdentifierFunction before calling this if
|
||||
* build ids are desirable.
|
||||
*/
|
||||
local_ref<JThrowable> getJavaExceptionForCppBackTrace();
|
||||
|
||||
local_ref<JThrowable> getJavaExceptionForCppBackTrace(const char* msg);
|
||||
|
||||
// For convenience, some exception names in java.lang are available here.
|
||||
|
||||
const char* const gJavaLangIllegalArgumentException = "java/lang/IllegalArgumentException";
|
||||
|
||||
}}
|
||||
42
libs/fbjni/cxx/fbjni/detail/Hybrid.cpp
Normal file
42
libs/fbjni/cxx/fbjni/detail/Hybrid.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
namespace detail {
|
||||
|
||||
local_ref<HybridData> HybridData::create() {
|
||||
return newInstance();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
void deleteNative(alias_ref<jclass>, jlong ptr) {
|
||||
delete reinterpret_cast<detail::BaseHybridClass*>(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void HybridDataOnLoad() {
|
||||
registerNatives("com/facebook/jni/HybridData$Destructor", {
|
||||
makeNativeMethod("deleteNative", deleteNative),
|
||||
});
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,18 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include <fb/assert.h>
|
||||
#include <fb/visibility.h>
|
||||
|
||||
#include "CoreClasses.h"
|
||||
|
||||
namespace facebook {
|
||||
@@ -25,13 +31,45 @@ public:
|
||||
virtual ~BaseHybridClass() {}
|
||||
};
|
||||
|
||||
struct FBEXPORT HybridData : public JavaClass<HybridData> {
|
||||
struct HybridData : public JavaClass<HybridData> {
|
||||
constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/HybridData;";
|
||||
void setNativePointer(std::unique_ptr<BaseHybridClass> new_value);
|
||||
BaseHybridClass* getNativePointer();
|
||||
static local_ref<HybridData> create();
|
||||
};
|
||||
|
||||
class HybridDestructor : public JavaClass<HybridDestructor> {
|
||||
public:
|
||||
static auto constexpr kJavaDescriptor = "Lcom/facebook/jni/HybridData$Destructor;";
|
||||
|
||||
detail::BaseHybridClass* getNativePointer();
|
||||
|
||||
void setNativePointer(std::unique_ptr<detail::BaseHybridClass> new_value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
detail::BaseHybridClass* getNativePointer(T t) {
|
||||
return getHolder(t)->getNativePointer();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void setNativePointer(T t, std::unique_ptr<detail::BaseHybridClass> new_value) {
|
||||
getHolder(t)->setNativePointer(std::move(new_value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
local_ref<HybridDestructor> getHolder(T t) {
|
||||
static auto holderField = t->getClass()->template getField<HybridDestructor::javaobject>("mDestructor");
|
||||
return t->getFieldValue(holderField);
|
||||
}
|
||||
|
||||
// JavaClass for HybridClassBase
|
||||
struct HybridClassBase : public JavaClass<HybridClassBase> {
|
||||
constexpr static auto kJavaDescriptor = "Lcom/facebook/jni/HybridClassBase;";
|
||||
|
||||
static bool isHybridClassBase(alias_ref<jclass> jclass) {
|
||||
return HybridClassBase::javaClassStatic()->isAssignableFrom(jclass);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Base, typename Enabled = void>
|
||||
struct HybridTraits {
|
||||
// This static assert should actually always fail if we don't use one of the
|
||||
@@ -66,7 +104,7 @@ struct HybridTraits<
|
||||
|
||||
// convert to HybridClass* from jhybridobject
|
||||
template <typename T>
|
||||
struct FBEXPORT Convert<
|
||||
struct Convert<
|
||||
T, typename std::enable_if<
|
||||
std::is_base_of<BaseHybridClass, typename std::remove_pointer<T>::type>::value>::type> {
|
||||
typedef typename std::remove_pointer<T>::type::jhybridobject jniType;
|
||||
@@ -91,7 +129,7 @@ struct RefReprType<T, typename std::enable_if<std::is_base_of<BaseHybridClass, T
|
||||
}
|
||||
|
||||
template <typename T, typename Base = detail::BaseHybridClass>
|
||||
class FBEXPORT HybridClass : public detail::HybridTraits<Base>::CxxBase {
|
||||
class HybridClass : public detail::HybridTraits<Base>::CxxBase {
|
||||
public:
|
||||
struct JavaPart : JavaClass<JavaPart, typename detail::HybridTraits<Base>::JavaBase> {
|
||||
// At this point, T is incomplete, and so we cannot access
|
||||
@@ -108,6 +146,7 @@ public:
|
||||
T* cthis();
|
||||
|
||||
friend class HybridClass;
|
||||
friend T;
|
||||
};
|
||||
|
||||
using jhybridobject = typename JavaPart::javaobject;
|
||||
@@ -137,7 +176,7 @@ protected:
|
||||
|
||||
static local_ref<detail::HybridData> makeHybridData(std::unique_ptr<T> cxxPart) {
|
||||
auto hybridData = detail::HybridData::create();
|
||||
hybridData->setNativePointer(std::move(cxxPart));
|
||||
setNativePointer(hybridData, std::move(cxxPart));
|
||||
return hybridData;
|
||||
}
|
||||
|
||||
@@ -146,6 +185,11 @@ protected:
|
||||
return makeHybridData(std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static void setCxxInstance(alias_ref<jhybridobject> o, Args&&... args) {
|
||||
setNativePointer(o, std::unique_ptr<T>(new T(std::forward<Args>(args)...)));
|
||||
}
|
||||
|
||||
public:
|
||||
// Factory method for creating a hybrid object where the arguments
|
||||
// are used to initialize the C++ part directly without passing them
|
||||
@@ -159,8 +203,20 @@ public:
|
||||
// C++ object fails, or any JNI methods throw.
|
||||
template <typename... Args>
|
||||
static local_ref<JavaPart> newObjectCxxArgs(Args&&... args) {
|
||||
auto hybridData = makeCxxInstance(std::forward<Args>(args)...);
|
||||
return JavaPart::newInstance(hybridData);
|
||||
static bool isHybrid = detail::HybridClassBase::isHybridClassBase(javaClassStatic());
|
||||
auto cxxPart = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
|
||||
local_ref<JavaPart> result;
|
||||
if (isHybrid) {
|
||||
result = JavaPart::newInstance();
|
||||
setNativePointer(result, std::move(cxxPart));
|
||||
}
|
||||
else {
|
||||
auto hybridData = makeHybridData(std::move(cxxPart));
|
||||
result = JavaPart::newInstance(hybridData);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO? Create reusable interface for Allocatable classes and use it to
|
||||
@@ -193,17 +249,23 @@ public:
|
||||
|
||||
template <typename T, typename B>
|
||||
inline T* HybridClass<T, B>::JavaPart::cthis() {
|
||||
detail::BaseHybridClass* result = 0;
|
||||
static bool isHybrid = detail::HybridClassBase::isHybridClassBase(this->getClass());
|
||||
if (isHybrid) {
|
||||
result = getNativePointer(this);
|
||||
} else {
|
||||
static auto field =
|
||||
HybridClass<T, B>::JavaPart::javaClassStatic()->template getField<detail::HybridData::javaobject>("mHybridData");
|
||||
auto hybridData = this->getFieldValue(field);
|
||||
if (!hybridData) {
|
||||
throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException");
|
||||
}
|
||||
|
||||
result = getNativePointer(hybridData);
|
||||
}
|
||||
|
||||
// I'd like to use dynamic_cast here, but -fno-rtti is the default.
|
||||
T* value = static_cast<T*>(hybridData->getNativePointer());
|
||||
// This would require some serious programmer error.
|
||||
FBASSERTMSGF(value != 0, "Incorrect C++ type in hybrid field");
|
||||
return value;
|
||||
return static_cast<T*>(result);
|
||||
};
|
||||
|
||||
template <typename T, typename B>
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace facebook {
|
||||
@@ -33,7 +42,7 @@ struct IteratorHelper : public JavaClass<IteratorHelper<E>> {
|
||||
value_type next() {
|
||||
static auto elementField =
|
||||
JavaBase_::javaClassStatic()->template getField<jobject>("mElement");
|
||||
return dynamic_ref_cast<E>(JavaBase_::getFieldValue(elementField));
|
||||
return dynamic_ref_cast<JniType<E>>(JavaBase_::getFieldValue(elementField));
|
||||
}
|
||||
|
||||
static void reset(value_type& v) {
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreClasses.h"
|
||||
49
libs/fbjni/cxx/fbjni/detail/JWeakReference.h
Normal file
49
libs/fbjni/cxx/fbjni/detail/JWeakReference.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreClasses.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
/**
|
||||
* Wrap Java's WeakReference instead of using JNI WeakGlobalRefs.
|
||||
* A WeakGlobalRef can yield a strong reference even after the object has been
|
||||
* finalized. See comment in the djinni library.
|
||||
* https://github.com/dropbox/djinni/blob/master/support-lib/jni/djinni_support.hpp
|
||||
*/
|
||||
template<typename T = jobject>
|
||||
class JWeakReference : public JavaClass<JWeakReference<T>> {
|
||||
|
||||
typedef JavaClass<JWeakReference<T>> JavaBase_;
|
||||
|
||||
public:
|
||||
static constexpr const char* kJavaDescriptor = "Ljava/lang/ref/WeakReference;";
|
||||
|
||||
static local_ref<JWeakReference<T>> newInstance(alias_ref<T> object) {
|
||||
return JavaBase_::newInstance(static_ref_cast<jobject>(object));
|
||||
}
|
||||
|
||||
local_ref<T> get() const {
|
||||
static const auto method = JavaBase_::javaClassStatic()->template getMethod<jobject()>("get");
|
||||
return static_ref_cast<T>(method(JavaBase_::self()));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
77
libs/fbjni/cxx/fbjni/detail/Log.h
Normal file
77
libs/fbjni/cxx/fbjni/detail/Log.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @file ALog.h
|
||||
*
|
||||
* Very simple (android only) logging. Define LOG_TAG to enable the macros.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
namespace log_ {
|
||||
// the weird name of this namespace is to avoid a conflict with the
|
||||
// function named log.
|
||||
|
||||
inline void loge(const char* tag, const char* msg) noexcept {
|
||||
__android_log_write(ANDROID_LOG_ERROR, tag, msg);
|
||||
}
|
||||
|
||||
template<typename... ARGS>
|
||||
inline void loge(const char* tag, const char* msg, ARGS... args) noexcept {
|
||||
__android_log_print(ANDROID_LOG_ERROR, tag, msg, args...);
|
||||
}
|
||||
|
||||
inline void logf(const char* tag, const char* msg) noexcept {
|
||||
__android_log_write(ANDROID_LOG_FATAL, tag, msg);
|
||||
}
|
||||
|
||||
template<typename... ARGS>
|
||||
inline void logf(const char* tag, const char* msg, ARGS... args) noexcept {
|
||||
__android_log_print(ANDROID_LOG_FATAL, tag, msg, args...);
|
||||
}
|
||||
|
||||
template<typename... ARGS>
|
||||
[[noreturn]]
|
||||
inline void logassert(const char* tag, const char* msg, ARGS... args) noexcept {
|
||||
__android_log_assert(0, tag, msg, args...);
|
||||
}
|
||||
|
||||
|
||||
#ifdef LOG_TAG
|
||||
# define FBJNI_LOGE(...) ::facebook::jni::log_::loge(LOG_TAG, __VA_ARGS__)
|
||||
# define FBJNI_LOGF(...) ::facebook::jni::log_::logf(LOG_TAG, __VA_ARGS__)
|
||||
# define FBJNI_ASSERT(cond) do { if (!(cond)) ::facebook::jni::log_::logassert(LOG_TAG, "%s", #cond); } while(0)
|
||||
#else
|
||||
# define FBJNI_LOGE(...) ::facebook::jni::log_::loge("log", __VA_ARGS__)
|
||||
# define FBJNI_LOGF(...) ::facebook::jni::log_::logf("log", __VA_ARGS__)
|
||||
# define FBJNI_ASSERT(cond) do { if (!(cond)) ::facebook::jni::log_::logassert("log", "%s", #cond); } while(0)
|
||||
#endif
|
||||
|
||||
}}}
|
||||
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
|
||||
# define FBJNI_LOGE(...) ((void)0)
|
||||
# define FBJNI_LOGF(...) (abort())
|
||||
# define FBJNI_ASSERT(cond) ((void)0)
|
||||
#endif
|
||||
43
libs/fbjni/cxx/fbjni/detail/Meta-forward.h
Normal file
43
libs/fbjni/cxx/fbjni/detail/Meta-forward.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
template<typename F>
|
||||
class JMethod;
|
||||
template<typename F>
|
||||
class JStaticMethod;
|
||||
template<typename F>
|
||||
class JNonvirtualMethod;
|
||||
template<typename F>
|
||||
struct JConstructor;
|
||||
template<typename F>
|
||||
class JField;
|
||||
template<typename F>
|
||||
class JStaticField;
|
||||
|
||||
/// Type traits for Java types (currently providing Java type descriptors)
|
||||
template<typename T>
|
||||
struct jtype_traits;
|
||||
|
||||
/// Type traits for Java methods (currently providing Java type descriptors)
|
||||
template<typename F>
|
||||
struct jmethod_traits;
|
||||
|
||||
}}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
@@ -15,10 +24,6 @@
|
||||
#include "References.h"
|
||||
#include "Boxed.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
@@ -63,31 +68,10 @@ local_ref<JArrayClass<jobject>::javaobject> makeArgsArray(Args... args) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
inline bool needsSlowPath(alias_ref<jobject> obj) {
|
||||
#if defined(__ANDROID__)
|
||||
// On Android 6.0, art crashes when attempting to call a function on a Proxy.
|
||||
// So, when we detect that case we must use the safe, slow workaround. That is,
|
||||
// we resolve the method id to the corresponding java.lang.reflect.Method object
|
||||
// and make the call via it's invoke() method.
|
||||
static auto android_sdk = ([] {
|
||||
char sdk_version_str[PROP_VALUE_MAX];
|
||||
__system_property_get("ro.build.version.sdk", sdk_version_str);
|
||||
return atoi(sdk_version_str);
|
||||
})();
|
||||
static auto is_bad_android = android_sdk == 23;
|
||||
if (!is_bad_android) return false;
|
||||
static auto proxy_class = findClassStatic("java/lang/reflect/Proxy");
|
||||
return obj->isInstanceOf(proxy_class);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void JMethod<void(Args...)>::operator()(alias_ref<jobject> self, Args... args) {
|
||||
inline void JMethod<void(Args...)>::operator()(alias_ref<jobject> self, Args... args) const {
|
||||
const auto env = Environment::current();
|
||||
env->CallVoidMethod(
|
||||
self.get(),
|
||||
@@ -98,10 +82,10 @@ inline void JMethod<void(Args...)>::operator()(alias_ref<jobject> self, Args...
|
||||
|
||||
#pragma push_macro("DEFINE_PRIMITIVE_CALL")
|
||||
#undef DEFINE_PRIMITIVE_CALL
|
||||
#define DEFINE_PRIMITIVE_CALL(TYPE, METHOD, CLASS) \
|
||||
#define DEFINE_PRIMITIVE_CALL(TYPE, METHOD) \
|
||||
template<typename... Args> \
|
||||
inline TYPE JMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, Args... args) { \
|
||||
const auto env = internal::getEnv(); \
|
||||
inline TYPE JMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, Args... args) const { \
|
||||
const auto env = Environment::current(); \
|
||||
auto result = env->Call ## METHOD ## Method( \
|
||||
self.get(), \
|
||||
getId(), \
|
||||
@@ -110,14 +94,14 @@ inline TYPE JMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, Args...
|
||||
return result; \
|
||||
}
|
||||
|
||||
DEFINE_PRIMITIVE_CALL(jboolean, Boolean, JBoolean)
|
||||
DEFINE_PRIMITIVE_CALL(jbyte, Byte, JByte)
|
||||
DEFINE_PRIMITIVE_CALL(jchar, Char, JCharacter)
|
||||
DEFINE_PRIMITIVE_CALL(jshort, Short, JShort)
|
||||
DEFINE_PRIMITIVE_CALL(jint, Int, JInteger)
|
||||
DEFINE_PRIMITIVE_CALL(jlong, Long, JLong)
|
||||
DEFINE_PRIMITIVE_CALL(jfloat, Float, JFloat)
|
||||
DEFINE_PRIMITIVE_CALL(jdouble, Double, JDouble)
|
||||
DEFINE_PRIMITIVE_CALL(jboolean, Boolean)
|
||||
DEFINE_PRIMITIVE_CALL(jbyte, Byte)
|
||||
DEFINE_PRIMITIVE_CALL(jchar, Char)
|
||||
DEFINE_PRIMITIVE_CALL(jshort, Short)
|
||||
DEFINE_PRIMITIVE_CALL(jint, Int)
|
||||
DEFINE_PRIMITIVE_CALL(jlong, Long)
|
||||
DEFINE_PRIMITIVE_CALL(jfloat, Float)
|
||||
DEFINE_PRIMITIVE_CALL(jdouble, Double)
|
||||
#pragma pop_macro("DEFINE_PRIMITIVE_CALL")
|
||||
|
||||
/// JMethod specialization for references that wraps the return value in a @ref local_ref
|
||||
@@ -132,13 +116,13 @@ class JMethod<R(Args...)> : public JMethodBase {
|
||||
JMethod(const JMethod& other) noexcept = default;
|
||||
|
||||
/// Invoke a method and return a local reference wrapping the result
|
||||
local_ref<JniRet> operator()(alias_ref<jobject> self, Args... args);
|
||||
local_ref<JniRet> operator()(alias_ref<jobject> self, Args... args) const;
|
||||
|
||||
friend class JClass;
|
||||
};
|
||||
|
||||
template<typename R, typename... Args>
|
||||
inline auto JMethod<R(Args...)>::operator()(alias_ref<jobject> self, Args... args) -> local_ref<JniRet> {
|
||||
inline auto JMethod<R(Args...)>::operator()(alias_ref<jobject> self, Args... args) const -> local_ref<JniRet> {
|
||||
const auto env = Environment::current();
|
||||
auto result = env->CallObjectMethod(
|
||||
self.get(),
|
||||
@@ -149,8 +133,8 @@ inline auto JMethod<R(Args...)>::operator()(alias_ref<jobject> self, Args... arg
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline void JStaticMethod<void(Args...)>::operator()(alias_ref<jclass> cls, Args... args) {
|
||||
const auto env = internal::getEnv();
|
||||
inline void JStaticMethod<void(Args...)>::operator()(alias_ref<jclass> cls, Args... args) const {
|
||||
const auto env = Environment::current();
|
||||
env->CallStaticVoidMethod(
|
||||
cls.get(),
|
||||
getId(),
|
||||
@@ -162,8 +146,8 @@ inline void JStaticMethod<void(Args...)>::operator()(alias_ref<jclass> cls, Args
|
||||
#undef DEFINE_PRIMITIVE_STATIC_CALL
|
||||
#define DEFINE_PRIMITIVE_STATIC_CALL(TYPE, METHOD) \
|
||||
template<typename... Args> \
|
||||
inline TYPE JStaticMethod<TYPE(Args...)>::operator()(alias_ref<jclass> cls, Args... args) { \
|
||||
const auto env = internal::getEnv(); \
|
||||
inline TYPE JStaticMethod<TYPE(Args...)>::operator()(alias_ref<jclass> cls, Args... args) const { \
|
||||
const auto env = Environment::current(); \
|
||||
auto result = env->CallStatic ## METHOD ## Method( \
|
||||
cls.get(), \
|
||||
getId(), \
|
||||
@@ -194,8 +178,8 @@ class JStaticMethod<R(Args...)> : public JMethodBase {
|
||||
JStaticMethod(const JStaticMethod& other) noexcept = default;
|
||||
|
||||
/// Invoke a method and return a local reference wrapping the result
|
||||
local_ref<JniRet> operator()(alias_ref<jclass> cls, Args... args) {
|
||||
const auto env = internal::getEnv();
|
||||
local_ref<JniRet> operator()(alias_ref<jclass> cls, Args... args) const {
|
||||
const auto env = Environment::current();
|
||||
auto result = env->CallStaticObjectMethod(
|
||||
cls.get(),
|
||||
getId(),
|
||||
@@ -209,8 +193,8 @@ class JStaticMethod<R(Args...)> : public JMethodBase {
|
||||
|
||||
template<typename... Args>
|
||||
inline void
|
||||
JNonvirtualMethod<void(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) {
|
||||
const auto env = internal::getEnv();
|
||||
JNonvirtualMethod<void(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const {
|
||||
const auto env = Environment::current();
|
||||
env->CallNonvirtualVoidMethod(
|
||||
self.get(),
|
||||
cls.get(),
|
||||
@@ -224,8 +208,8 @@ JNonvirtualMethod<void(Args...)>::operator()(alias_ref<jobject> self, alias_ref<
|
||||
#define DEFINE_PRIMITIVE_NON_VIRTUAL_CALL(TYPE, METHOD) \
|
||||
template<typename... Args> \
|
||||
inline TYPE \
|
||||
JNonvirtualMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) { \
|
||||
const auto env = internal::getEnv(); \
|
||||
JNonvirtualMethod<TYPE(Args...)>::operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const { \
|
||||
const auto env = Environment::current(); \
|
||||
auto result = env->CallNonvirtual ## METHOD ## Method( \
|
||||
self.get(), \
|
||||
cls.get(), \
|
||||
@@ -256,8 +240,8 @@ class JNonvirtualMethod<R(Args...)> : public JMethodBase {
|
||||
JNonvirtualMethod(const JNonvirtualMethod& other) noexcept = default;
|
||||
|
||||
/// Invoke a method and return a local reference wrapping the result
|
||||
local_ref<JniRet> operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args){
|
||||
const auto env = internal::getEnv();
|
||||
local_ref<JniRet> operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const {
|
||||
const auto env = Environment::current();
|
||||
auto result = env->CallNonvirtualObjectMethod(
|
||||
self.get(),
|
||||
cls.get(),
|
||||
@@ -306,13 +290,13 @@ inline jfieldID JField<T>::getId() const noexcept {
|
||||
#define DEFINE_FIELD_PRIMITIVE_GET_SET(TYPE, METHOD) \
|
||||
template<> \
|
||||
inline TYPE JField<TYPE>::get(jobject object) const noexcept { \
|
||||
const auto env = internal::getEnv(); \
|
||||
const auto env = Environment::current(); \
|
||||
return env->Get ## METHOD ## Field(object, field_id_); \
|
||||
} \
|
||||
\
|
||||
template<> \
|
||||
inline void JField<TYPE>::set(jobject object, TYPE value) noexcept { \
|
||||
const auto env = internal::getEnv(); \
|
||||
const auto env = Environment::current(); \
|
||||
env->Set ## METHOD ## Field(object, field_id_, value); \
|
||||
}
|
||||
|
||||
@@ -328,12 +312,12 @@ DEFINE_FIELD_PRIMITIVE_GET_SET(jdouble, Double)
|
||||
|
||||
template<typename T>
|
||||
inline T JField<T>::get(jobject object) const noexcept {
|
||||
return static_cast<T>(internal::getEnv()->GetObjectField(object, field_id_));
|
||||
return static_cast<T>(Environment::current()->GetObjectField(object, field_id_));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void JField<T>::set(jobject object, T value) noexcept {
|
||||
internal::getEnv()->SetObjectField(object, field_id_, static_cast<jobject>(value));
|
||||
Environment::current()->SetObjectField(object, field_id_, static_cast<jobject>(value));
|
||||
}
|
||||
|
||||
// JStaticField<T> /////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -358,13 +342,13 @@ inline jfieldID JStaticField<T>::getId() const noexcept {
|
||||
#define DEFINE_STATIC_FIELD_PRIMITIVE_GET_SET(TYPE, METHOD) \
|
||||
template<> \
|
||||
inline TYPE JStaticField<TYPE>::get(jclass jcls) const noexcept { \
|
||||
const auto env = internal::getEnv(); \
|
||||
const auto env = Environment::current(); \
|
||||
return env->GetStatic ## METHOD ## Field(jcls, field_id_); \
|
||||
} \
|
||||
\
|
||||
template<> \
|
||||
inline void JStaticField<TYPE>::set(jclass jcls, TYPE value) noexcept { \
|
||||
const auto env = internal::getEnv(); \
|
||||
const auto env = Environment::current(); \
|
||||
env->SetStatic ## METHOD ## Field(jcls, field_id_, value); \
|
||||
}
|
||||
|
||||
@@ -380,13 +364,13 @@ DEFINE_STATIC_FIELD_PRIMITIVE_GET_SET(jdouble, Double)
|
||||
|
||||
template<typename T>
|
||||
inline T JStaticField<T>::get(jclass jcls) const noexcept {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
return static_cast<T>(env->GetStaticObjectField(jcls, field_id_));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void JStaticField<T>::set(jclass jcls, T value) noexcept {
|
||||
internal::getEnv()->SetStaticObjectField(jcls, field_id_, value);
|
||||
Environment::current()->SetStaticObjectField(jcls, field_id_, value);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @file meta.h
|
||||
*
|
||||
* Provides wrappers for meta data such as methods and fields.
|
||||
@@ -81,7 +90,7 @@ class JMethod<TYPE(Args...)> : public JMethodBase {
|
||||
JMethod() noexcept {}; \
|
||||
JMethod(const JMethod& other) noexcept = default; \
|
||||
\
|
||||
TYPE operator()(alias_ref<jobject> self, Args... args); \
|
||||
TYPE operator()(alias_ref<jobject> self, Args... args) const; \
|
||||
\
|
||||
friend class JClass; \
|
||||
}
|
||||
@@ -131,7 +140,7 @@ class JStaticMethod<TYPE(Args...)> : public JMethodBase { \
|
||||
JStaticMethod() noexcept {}; \
|
||||
JStaticMethod(const JStaticMethod& other) noexcept = default; \
|
||||
\
|
||||
TYPE operator()(alias_ref<jclass> cls, Args... args); \
|
||||
TYPE operator()(alias_ref<jclass> cls, Args... args) const; \
|
||||
\
|
||||
friend class JClass; \
|
||||
}
|
||||
@@ -171,7 +180,7 @@ class JNonvirtualMethod<TYPE(Args...)> : public JMethodBase { \
|
||||
JNonvirtualMethod() noexcept {}; \
|
||||
JNonvirtualMethod(const JNonvirtualMethod& other) noexcept = default; \
|
||||
\
|
||||
TYPE operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args); \
|
||||
TYPE operator()(alias_ref<jobject> self, alias_ref<jclass> cls, Args... args) const; \
|
||||
\
|
||||
friend class JClass; \
|
||||
}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2004-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
@@ -100,7 +109,21 @@ template <typename T>
|
||||
struct Convert<global_ref<T>> {
|
||||
typedef JniType<T> jniType;
|
||||
// No automatic synthesis of global_ref
|
||||
static jniType toJniRet(global_ref<jniType> t) {
|
||||
static jniType toJniRet(global_ref<jniType>&& t) {
|
||||
// If this gets called, ownership the global_ref was passed in here. (It's
|
||||
// probably a copy of a persistent global_ref made when a function was
|
||||
// declared to return a global_ref, but it could moved out or otherwise not
|
||||
// referenced elsewhere. Doesn't matter.) Either way, the only safe way
|
||||
// to return it is to make a local_ref, release it, and return the
|
||||
// underlying local jobject.
|
||||
auto ret = make_local(t);
|
||||
return ret.release();
|
||||
}
|
||||
static jniType toJniRet(const global_ref<jniType>& t) {
|
||||
// If this gets called, the function was declared to return const&. We
|
||||
// have a ref to a global_ref whose lifetime will exceed this call, so we
|
||||
// can just get the underlying jobject and return it to java without
|
||||
// needing to make a local_ref.
|
||||
return t.get();
|
||||
}
|
||||
static jniType toCall(global_ref<jniType> t) {
|
||||
@@ -1,16 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
#include <atomic>
|
||||
|
||||
#include "Environment.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
@@ -19,7 +30,8 @@ namespace internal {
|
||||
|
||||
// Statistics mostly provided for test (only updated if FBJNI_DEBUG_REFS is defined)
|
||||
struct ReferenceStats {
|
||||
std::atomic_uint locals_deleted, globals_deleted, weaks_deleted;
|
||||
std::atomic_uint locals_created, globals_created, weaks_created,
|
||||
locals_deleted, globals_deleted, weaks_deleted;
|
||||
|
||||
void reset() noexcept;
|
||||
};
|
||||
@@ -33,7 +45,10 @@ extern ReferenceStats g_reference_stats;
|
||||
|
||||
inline jobject LocalReferenceAllocator::newReference(jobject original) const {
|
||||
internal::dbglog("Local new: %p", original);
|
||||
auto ref = internal::getEnv()->NewLocalRef(original);
|
||||
#ifdef FBJNI_DEBUG_REFS
|
||||
++internal::g_reference_stats.locals_created;
|
||||
#endif
|
||||
auto ref = Environment::current()->NewLocalRef(original);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
return ref;
|
||||
}
|
||||
@@ -46,15 +61,12 @@ inline void LocalReferenceAllocator::deleteReference(jobject reference) const no
|
||||
++internal::g_reference_stats.locals_deleted;
|
||||
#endif
|
||||
assert(verifyReference(reference));
|
||||
internal::getEnv()->DeleteLocalRef(reference);
|
||||
Environment::current()->DeleteLocalRef(reference);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool LocalReferenceAllocator::verifyReference(jobject reference) const noexcept {
|
||||
if (!reference || !internal::doesGetObjectRefTypeWork()) {
|
||||
return true;
|
||||
}
|
||||
return internal::getEnv()->GetObjectRefType(reference) == JNILocalRefType;
|
||||
return isObjectRefType(reference, JNILocalRefType);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +74,10 @@ inline bool LocalReferenceAllocator::verifyReference(jobject reference) const no
|
||||
|
||||
inline jobject GlobalReferenceAllocator::newReference(jobject original) const {
|
||||
internal::dbglog("Global new: %p", original);
|
||||
auto ref = internal::getEnv()->NewGlobalRef(original);
|
||||
#ifdef FBJNI_DEBUG_REFS
|
||||
++internal::g_reference_stats.globals_created;
|
||||
#endif
|
||||
auto ref = Environment::current()->NewGlobalRef(original);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
return ref;
|
||||
}
|
||||
@@ -75,15 +90,12 @@ inline void GlobalReferenceAllocator::deleteReference(jobject reference) const n
|
||||
++internal::g_reference_stats.globals_deleted;
|
||||
#endif
|
||||
assert(verifyReference(reference));
|
||||
internal::getEnv()->DeleteGlobalRef(reference);
|
||||
Environment::current()->DeleteGlobalRef(reference);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool GlobalReferenceAllocator::verifyReference(jobject reference) const noexcept {
|
||||
if (!reference || !internal::doesGetObjectRefTypeWork()) {
|
||||
return true;
|
||||
}
|
||||
return internal::getEnv()->GetObjectRefType(reference) == JNIGlobalRefType;
|
||||
return isObjectRefType(reference, JNIGlobalRefType);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +103,10 @@ inline bool GlobalReferenceAllocator::verifyReference(jobject reference) const n
|
||||
|
||||
inline jobject WeakGlobalReferenceAllocator::newReference(jobject original) const {
|
||||
internal::dbglog("Weak global new: %p", original);
|
||||
auto ref = internal::getEnv()->NewWeakGlobalRef(original);
|
||||
#ifdef FBJNI_DEBUG_REFS
|
||||
++internal::g_reference_stats.weaks_created;
|
||||
#endif
|
||||
auto ref = Environment::current()->NewWeakGlobalRef(original);
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
return ref;
|
||||
}
|
||||
@@ -104,15 +119,12 @@ inline void WeakGlobalReferenceAllocator::deleteReference(jobject reference) con
|
||||
++internal::g_reference_stats.weaks_deleted;
|
||||
#endif
|
||||
assert(verifyReference(reference));
|
||||
internal::getEnv()->DeleteWeakGlobalRef(reference);
|
||||
Environment::current()->DeleteWeakGlobalRef(reference);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool WeakGlobalReferenceAllocator::verifyReference(jobject reference) const noexcept {
|
||||
if (!reference || !internal::doesGetObjectRefTypeWork()) {
|
||||
return true;
|
||||
}
|
||||
return internal::getEnv()->GetObjectRefType(reference) == JNIWeakGlobalRefType;
|
||||
return isObjectRefType(reference, JNIWeakGlobalRefType);
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ReferenceAllocators.h
|
||||
*
|
||||
@@ -14,14 +23,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace facebook { namespace jni {
|
||||
|
||||
/// Allocator that handles local references
|
||||
class FBEXPORT LocalReferenceAllocator {
|
||||
class LocalReferenceAllocator {
|
||||
public:
|
||||
jobject newReference(jobject original) const;
|
||||
void deleteReference(jobject reference) const noexcept;
|
||||
@@ -29,7 +36,7 @@ class FBEXPORT LocalReferenceAllocator {
|
||||
};
|
||||
|
||||
/// Allocator that handles global references
|
||||
class FBEXPORT GlobalReferenceAllocator {
|
||||
class GlobalReferenceAllocator {
|
||||
public:
|
||||
jobject newReference(jobject original) const;
|
||||
void deleteReference(jobject reference) const noexcept;
|
||||
@@ -37,23 +44,20 @@ class FBEXPORT GlobalReferenceAllocator {
|
||||
};
|
||||
|
||||
/// Allocator that handles weak global references
|
||||
class FBEXPORT WeakGlobalReferenceAllocator {
|
||||
class WeakGlobalReferenceAllocator {
|
||||
public:
|
||||
jobject newReference(jobject original) const;
|
||||
void deleteReference(jobject reference) const noexcept;
|
||||
bool verifyReference(jobject reference) const noexcept;
|
||||
};
|
||||
|
||||
/// @cond INTERNAL
|
||||
namespace internal {
|
||||
|
||||
/**
|
||||
* @return true iff env->GetObjectRefType is expected to work properly.
|
||||
* @return Helper based on GetObjectRefType. Since this isn't defined
|
||||
* on all versions of Java or Android, if the type can't be
|
||||
* determined, this returns true. If reference is nullptr, returns
|
||||
* true.
|
||||
*/
|
||||
FBEXPORT bool doesGetObjectRefTypeWork();
|
||||
|
||||
}
|
||||
/// @endcond
|
||||
bool isObjectRefType(jobject reference, jobjectRefType refType);
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ReferenceAllocators.h"
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <new>
|
||||
@@ -488,18 +497,21 @@ enable_if_t<IsPlainJniReference<T>(), decltype(static_ref_cast<T>(ref))>
|
||||
return decltype(static_ref_cast<T>(ref))();
|
||||
}
|
||||
|
||||
std::string target_class_name{jtype_traits<T>::base_name()};
|
||||
static alias_ref<jclass> target_class = findClassStatic(jtype_traits<T>::base_name().c_str());
|
||||
if (!target_class) {
|
||||
throwNewJavaException("java/lang/ClassCastException",
|
||||
"Could not find class %s.",
|
||||
jtype_traits<T>::base_name().c_str());
|
||||
|
||||
// If not found, will throw an exception.
|
||||
alias_ref<jclass> target_class = findClassStatic(target_class_name.c_str());
|
||||
}
|
||||
|
||||
local_ref<jclass> source_class = ref->getClass();
|
||||
|
||||
if ( ! source_class->isAssignableFrom(target_class)) {
|
||||
if (!target_class->isAssignableFrom(source_class)) {
|
||||
throwNewJavaException("java/lang/ClassCastException",
|
||||
"Tried to cast from %s to %s.",
|
||||
source_class->toString().c_str(),
|
||||
target_class_name.c_str());
|
||||
jtype_traits<T>::base_name().c_str());
|
||||
}
|
||||
|
||||
return static_ref_cast<T>(ref);
|
||||
75
libs/fbjni/cxx/fbjni/detail/References.cpp
Normal file
75
libs/fbjni/cxx/fbjni/detail/References.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "References.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
JniLocalScope::JniLocalScope(JNIEnv* env, jint capacity)
|
||||
: env_(env) {
|
||||
hasFrame_ = false;
|
||||
auto pushResult = env->PushLocalFrame(capacity);
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(pushResult < 0);
|
||||
hasFrame_ = true;
|
||||
}
|
||||
|
||||
JniLocalScope::~JniLocalScope() {
|
||||
if (hasFrame_) {
|
||||
env_->PopLocalFrame(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
int32_t getAndroidApiLevel() {
|
||||
auto cls = findClassLocal("android/os/Build$VERSION");
|
||||
auto fld = cls->getStaticField<int32_t>("SDK_INT");
|
||||
if (fld) {
|
||||
return cls->getStaticFieldValue(fld);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool doesGetObjectRefTypeWork() {
|
||||
auto level = getAndroidApiLevel();
|
||||
return level >= 14;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool doesGetObjectRefTypeWork() {
|
||||
auto jni_version = Environment::current()->GetVersion();
|
||||
return jni_version >= JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool isObjectRefType(jobject reference, jobjectRefType refType) {
|
||||
static bool getObjectRefTypeWorks = doesGetObjectRefTypeWork();
|
||||
|
||||
return
|
||||
!reference ||
|
||||
!getObjectRefTypeWorks ||
|
||||
Environment::current()->GetObjectRefType(reference) == refType;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/** @file References.h
|
||||
*
|
||||
* Functionality similar to smart pointers, but for references into the VM. Four main reference
|
||||
@@ -74,8 +84,6 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
#include "ReferenceAllocators.h"
|
||||
#include "TypeTraits.h"
|
||||
#include "References-forward.h"
|
||||
@@ -337,7 +345,7 @@ class weak_ref : public base_owned_ref<T, WeakGlobalReferenceAllocator> {
|
||||
: base_owned_ref<T, Allocator>{} {}
|
||||
|
||||
/// Create a null reference
|
||||
explicit weak_ref(std::nullptr_t) noexcept
|
||||
/* implicit */ weak_ref(std::nullptr_t) noexcept
|
||||
: base_owned_ref<T, Allocator>{nullptr} {}
|
||||
|
||||
/// Copy constructor (note creates a new reference)
|
||||
@@ -406,7 +414,7 @@ class basic_strong_ref : public base_owned_ref<T, Alloc> {
|
||||
: base_owned_ref<T, Alloc>{} {}
|
||||
|
||||
/// Create a null reference
|
||||
explicit basic_strong_ref(std::nullptr_t) noexcept
|
||||
/* implicit */ basic_strong_ref(std::nullptr_t) noexcept
|
||||
: base_owned_ref<T, Alloc>{nullptr} {}
|
||||
|
||||
/// Copy constructor (note creates a new reference)
|
||||
@@ -493,7 +501,7 @@ class alias_ref {
|
||||
alias_ref() noexcept;
|
||||
|
||||
/// Create a null reference
|
||||
alias_ref(std::nullptr_t) noexcept;
|
||||
/* implicit */ alias_ref(std::nullptr_t) noexcept;
|
||||
|
||||
/// Copy constructor
|
||||
alias_ref(const alias_ref& other) noexcept;
|
||||
@@ -554,7 +562,7 @@ class alias_ref {
|
||||
* This is useful when you have a call which is initiated from C++-land, and therefore
|
||||
* doesn't automatically get a local JNI frame managed for you by the JNI framework.
|
||||
*/
|
||||
class FBEXPORT JniLocalScope {
|
||||
class JniLocalScope {
|
||||
public:
|
||||
JniLocalScope(JNIEnv* p_env, jint capacity);
|
||||
~JniLocalScope();
|
||||
156
libs/fbjni/cxx/fbjni/detail/Registration-inl.h
Normal file
156
libs/fbjni/cxx/fbjni/detail/Registration-inl.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Exceptions.h"
|
||||
#include "Hybrid.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
namespace detail {
|
||||
|
||||
#ifdef __i386__
|
||||
// X86 ABI forces 16 byte stack allignment on calls. Unfortunately
|
||||
// sometimes Dalvik chooses not to obey the ABI:
|
||||
// - https://code.google.com/p/android/issues/detail?id=61012
|
||||
// - https://android.googlesource.com/platform/ndk/+/81696d2%5E!/
|
||||
// Therefore, we tell the compiler to re-align the stack on entry
|
||||
// to our JNI functions.
|
||||
#define JNI_ENTRY_POINT __attribute__((force_align_arg_pointer))
|
||||
#else
|
||||
#define JNI_ENTRY_POINT
|
||||
#endif
|
||||
|
||||
template <typename R>
|
||||
struct CreateDefault {
|
||||
static R create() {
|
||||
return R{};
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CreateDefault<void> {
|
||||
static void create() {}
|
||||
};
|
||||
|
||||
template <typename R>
|
||||
using Converter = Convert<typename std::decay<R>::type>;
|
||||
|
||||
template <typename F, F func, typename R, typename... Args>
|
||||
struct WrapForVoidReturn {
|
||||
static typename Converter<R>::jniType call(Args&&... args) {
|
||||
return Converter<R>::toJniRet(func(std::forward<Args>(args)...));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, F func, typename... Args>
|
||||
struct WrapForVoidReturn<F, func, void, Args...> {
|
||||
static void call(Args&&... args) {
|
||||
func(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
// registration wrapper for legacy JNI-style functions
|
||||
template<typename F, F func, typename C, typename R, typename... Args>
|
||||
struct BareJniWrapper {
|
||||
JNI_ENTRY_POINT static R call(JNIEnv* env, jobject obj, Args... args) {
|
||||
detail::JniEnvCacher jec(env);
|
||||
try {
|
||||
return (*func)(env, static_cast<JniType<C>>(obj), args...);
|
||||
} catch (...) {
|
||||
translatePendingCppExceptionToJavaException();
|
||||
return CreateDefault<R>::create();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// registration wrappers for functions, with autoconversion of arguments.
|
||||
template<typename F, F func, typename C, typename R, typename... Args>
|
||||
struct FunctionWrapper {
|
||||
using jniRet = typename Converter<R>::jniType;
|
||||
JNI_ENTRY_POINT static jniRet call(JNIEnv* env, jobject obj, typename Converter<Args>::jniType... args) {
|
||||
detail::JniEnvCacher jec(env);
|
||||
try {
|
||||
return WrapForVoidReturn<F, func, R, JniType<C>, Args...>::call(
|
||||
static_cast<JniType<C>>(obj), Converter<Args>::fromJni(args)...);
|
||||
} catch (...) {
|
||||
translatePendingCppExceptionToJavaException();
|
||||
return CreateDefault<jniRet>::create();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// registration wrappers for non-static methods, with autoconvertion of arguments.
|
||||
template<typename M, M method, typename C, typename R, typename... Args>
|
||||
struct MethodWrapper {
|
||||
using jhybrid = typename C::jhybridobject;
|
||||
static R dispatch(alias_ref<jhybrid> ref, Args&&... args) {
|
||||
try {
|
||||
// This is usually a noop, but if the hybrid object is a
|
||||
// base class of other classes which register JNI methods,
|
||||
// this will get the right type for the registered method.
|
||||
auto cobj = static_cast<C*>(ref->cthis());
|
||||
return (cobj->*method)(std::forward<Args>(args)...);
|
||||
} catch (const std::exception& ex) {
|
||||
C::mapException(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
JNI_ENTRY_POINT static typename Converter<R>::jniType call(
|
||||
JNIEnv* env, jobject obj, typename Converter<Args>::jniType... args) {
|
||||
return FunctionWrapper<R(*)(alias_ref<jhybrid>, Args&&...), dispatch, jhybrid, R, Args...>::call(env, obj, args...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename F, F func, typename C, typename R, typename... Args>
|
||||
inline NativeMethodWrapper* exceptionWrapJNIMethod(R (*)(JNIEnv*, C, Args... args)) {
|
||||
// This intentionally erases the real type; JNI will do it anyway
|
||||
return reinterpret_cast<NativeMethodWrapper*>(&(BareJniWrapper<F, func, C, R, Args...>::call));
|
||||
}
|
||||
|
||||
template<typename F, F func, typename C, typename R, typename... Args>
|
||||
inline NativeMethodWrapper* exceptionWrapJNIMethod(R (*)(alias_ref<C>, Args... args)) {
|
||||
// This intentionally erases the real type; JNI will do it anyway
|
||||
return reinterpret_cast<NativeMethodWrapper*>(&(FunctionWrapper<F, func, C, R, Args...>::call));
|
||||
}
|
||||
|
||||
template<typename M, M method, typename C, typename R, typename... Args>
|
||||
inline NativeMethodWrapper* exceptionWrapJNIMethod(R (C::*method0)(Args... args)) {
|
||||
// This intentionally erases the real type; JNI will do it anyway
|
||||
return reinterpret_cast<NativeMethodWrapper*>(&(MethodWrapper<M, method, C, R, Args...>::call));
|
||||
}
|
||||
|
||||
template<typename R, typename C, typename... Args>
|
||||
inline std::string makeDescriptor(R (*)(JNIEnv*, C, Args... args)) {
|
||||
return jmethod_traits<R(Args...)>::descriptor();
|
||||
}
|
||||
|
||||
template<typename R, typename C, typename... Args>
|
||||
inline std::string makeDescriptor(R (*)(alias_ref<C>, Args... args)) {
|
||||
return jmethod_traits_from_cxx<R(Args...)>::descriptor();
|
||||
}
|
||||
|
||||
template<typename R, typename C, typename... Args>
|
||||
inline std::string makeDescriptor(R (C::*)(Args... args)) {
|
||||
return jmethod_traits_from_cxx<R(Args...)>::descriptor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
@@ -18,28 +27,14 @@ namespace detail {
|
||||
// This uses the real JNI function as a non-type template parameter to
|
||||
// cause a (static member) function to exist with the same signature,
|
||||
// but with try/catch exception translation.
|
||||
template<typename F, F func, typename C, typename... Args>
|
||||
NativeMethodWrapper* exceptionWrapJNIMethod(void (*func0)(JNIEnv*, jobject, Args... args));
|
||||
|
||||
// Same as above, but for non-void return types.
|
||||
template<typename F, F func, typename C, typename R, typename... Args>
|
||||
NativeMethodWrapper* exceptionWrapJNIMethod(R (*func0)(JNIEnv*, jobject, Args... args));
|
||||
|
||||
// Automatically wrap object argument, and don't take env explicitly.
|
||||
template<typename F, F func, typename C, typename... Args>
|
||||
NativeMethodWrapper* exceptionWrapJNIMethod(void (*func0)(alias_ref<C>, Args... args));
|
||||
|
||||
// Automatically wrap object argument, and don't take env explicitly,
|
||||
// non-void return type.
|
||||
template<typename F, F func, typename C, typename R, typename... Args>
|
||||
NativeMethodWrapper* exceptionWrapJNIMethod(R (*func0)(alias_ref<C>, Args... args));
|
||||
|
||||
// Extract C++ instance from object, and invoke given method on it.
|
||||
template<typename M, M method, typename C, typename... Args>
|
||||
NativeMethodWrapper* exceptionWrapJNIMethod(void (C::*method0)(Args... args));
|
||||
|
||||
// Extract C++ instance from object, and invoke given method on it,
|
||||
// non-void return type
|
||||
template<typename M, M method, typename C, typename R, typename... Args>
|
||||
NativeMethodWrapper* exceptionWrapJNIMethod(R (C::*method0)(Args... args));
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
@@ -1,15 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <jni/LocalString.h>
|
||||
#include <fb/Environment.h>
|
||||
#include <fb/assert.h>
|
||||
|
||||
#include <vector>
|
||||
#include "utf8.h"
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
@@ -23,7 +30,9 @@ const uint16_t kUtf16HighSubHighBoundary = 0xDC00;
|
||||
const uint16_t kUtf16LowSubHighBoundary = 0xE000;
|
||||
|
||||
inline void encode3ByteUTF8(char32_t code, uint8_t* out) {
|
||||
FBASSERTMSGF((code & 0xffff0000) == 0, "3 byte utf-8 encodings only valid for up to 16 bits");
|
||||
if ((code & 0xffff0000) != 0) {
|
||||
FBJNI_LOGF("3 byte utf-8 encodings only valid for up to 16 bits");
|
||||
}
|
||||
|
||||
out[0] = 0xE0 | (code >> 12);
|
||||
out[1] = 0x80 | ((code >> 6) & 0x3F);
|
||||
@@ -37,7 +46,9 @@ inline char32_t decode3ByteUTF8(const uint8_t* in) {
|
||||
}
|
||||
|
||||
inline void encode4ByteUTF8(char32_t code, std::string& out, size_t offset) {
|
||||
FBASSERTMSGF((code & 0xfff80000) == 0, "4 byte utf-8 encodings only valid for up to 21 bits");
|
||||
if ((code & 0xfff80000) != 0) {
|
||||
FBJNI_LOGF("4 byte utf-8 encodings only valid for up to 21 bits");
|
||||
}
|
||||
|
||||
out[offset] = (char) (0xF0 | (code >> 18));
|
||||
out[offset + 1] = (char) (0x80 | ((code >> 12) & 0x3F));
|
||||
@@ -101,9 +112,13 @@ void utf8ToModifiedUTF8(const uint8_t* utf8, size_t len, uint8_t* modified, size
|
||||
{
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < len; ) {
|
||||
FBASSERTMSGF(j < modifiedBufLen, "output buffer is too short");
|
||||
if (j >= modifiedBufLen) {
|
||||
FBJNI_LOGF("output buffer is too short");
|
||||
}
|
||||
if (utf8[i] == 0) {
|
||||
FBASSERTMSGF(j + 1 < modifiedBufLen, "output buffer is too short");
|
||||
if (j + 1 >= modifiedBufLen) {
|
||||
FBJNI_LOGF("output buffer is too short");
|
||||
}
|
||||
modified[j] = 0xc0;
|
||||
modified[j + 1] = 0x80;
|
||||
i += 1;
|
||||
@@ -143,14 +158,18 @@ void utf8ToModifiedUTF8(const uint8_t* utf8, size_t len, uint8_t* modified, size
|
||||
}
|
||||
|
||||
// encode each as a 3 byte surrogate value
|
||||
FBASSERTMSGF(j + 5 < modifiedBufLen, "output buffer is too short");
|
||||
if (j + 5 >= modifiedBufLen) {
|
||||
FBJNI_LOGF("output buffer is too short");
|
||||
}
|
||||
encode3ByteUTF8(first, modified + j);
|
||||
encode3ByteUTF8(second, modified + j + 3);
|
||||
i += 4;
|
||||
j += 6;
|
||||
}
|
||||
|
||||
FBASSERTMSGF(j < modifiedBufLen, "output buffer is too short");
|
||||
if (j >= modifiedBufLen) {
|
||||
FBJNI_LOGF("output buffer is too short");
|
||||
}
|
||||
modified[j++] = '\0';
|
||||
}
|
||||
|
||||
@@ -265,46 +284,5 @@ std::string utf16toUTF8(const uint16_t* utf16String, size_t utf16StringLen) noex
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LocalString::LocalString(const std::string& str)
|
||||
{
|
||||
size_t modlen = detail::modifiedLength(str);
|
||||
if (modlen == str.size()) {
|
||||
// no supplementary characters, build jstring from input buffer
|
||||
m_string = Environment::current()->NewStringUTF(str.data());
|
||||
return;
|
||||
}
|
||||
auto modified = std::vector<char>(modlen + 1); // allocate extra byte for \0
|
||||
detail::utf8ToModifiedUTF8(
|
||||
reinterpret_cast<const uint8_t*>(str.data()), str.size(),
|
||||
reinterpret_cast<uint8_t*>(modified.data()), modified.size());
|
||||
m_string = Environment::current()->NewStringUTF(modified.data());
|
||||
}
|
||||
|
||||
LocalString::LocalString(const char* str)
|
||||
{
|
||||
size_t len;
|
||||
size_t modlen = detail::modifiedLength(reinterpret_cast<const uint8_t*>(str), &len);
|
||||
if (modlen == len) {
|
||||
// no supplementary characters, build jstring from input buffer
|
||||
m_string = Environment::current()->NewStringUTF(str);
|
||||
return;
|
||||
}
|
||||
auto modified = std::vector<char>(modlen + 1); // allocate extra byte for \0
|
||||
detail::utf8ToModifiedUTF8(
|
||||
reinterpret_cast<const uint8_t*>(str), len,
|
||||
reinterpret_cast<uint8_t*>(modified.data()), modified.size());
|
||||
m_string = Environment::current()->NewStringUTF(modified.data());
|
||||
}
|
||||
|
||||
LocalString::~LocalString() {
|
||||
Environment::current()->DeleteLocalRef(m_string);
|
||||
}
|
||||
|
||||
std::string fromJString(JNIEnv* env, jstring str) {
|
||||
auto utf16String = JStringUtf16Extractor(env, str);
|
||||
auto length = env->GetStringLength(str);
|
||||
return detail::utf16toUTF8(utf16String, length);
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -1,18 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
@@ -43,28 +50,18 @@ std::string utf16toUTF8(const uint16_t* utf16Bytes, size_t len) noexcept;
|
||||
// - http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html
|
||||
// - https://docs.oracle.com/javase/6/docs/api/java/io/DataInput.html#modified-utf-8
|
||||
|
||||
class FBEXPORT LocalString {
|
||||
public:
|
||||
// Assumes UTF8 encoding and make a required convertion to modified UTF-8 when the string
|
||||
// contains unicode supplementary characters.
|
||||
explicit LocalString(const std::string& str);
|
||||
explicit LocalString(const char* str);
|
||||
jstring string() const {
|
||||
return m_string;
|
||||
}
|
||||
~LocalString();
|
||||
private:
|
||||
jstring m_string;
|
||||
};
|
||||
|
||||
// JString to UTF16 extractor using RAII idiom
|
||||
// JString to UTF16 extractor using RAII idiom. Note that the
|
||||
// ctor/dtor use GetStringCritical/ReleaseStringCritical, so this
|
||||
// class is subject to the restrictions imposed by those functions.
|
||||
class JStringUtf16Extractor {
|
||||
public:
|
||||
JStringUtf16Extractor(JNIEnv* env, jstring javaString)
|
||||
: env_(env)
|
||||
, javaString_(javaString)
|
||||
, length_(0)
|
||||
, utf16String_(nullptr) {
|
||||
if (env_ && javaString_) {
|
||||
length_ = env_->GetStringLength(javaString_);
|
||||
utf16String_ = env_->GetStringCritical(javaString_, nullptr);
|
||||
}
|
||||
}
|
||||
@@ -75,18 +72,20 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
operator const jchar* () const {
|
||||
const jsize length() const {
|
||||
return length_;
|
||||
}
|
||||
|
||||
const jchar* chars() const {
|
||||
return utf16String_;
|
||||
}
|
||||
|
||||
private:
|
||||
JNIEnv* env_;
|
||||
jstring javaString_;
|
||||
jsize length_;
|
||||
const jchar* utf16String_;
|
||||
};
|
||||
|
||||
// The string from JNI is converted to standard UTF-8 if the string contains supplementary
|
||||
// characters.
|
||||
FBEXPORT std::string fromJString(JNIEnv* env, jstring str);
|
||||
|
||||
} }
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <fb/fbjni.h>
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <jni/LocalString.h>
|
||||
#include <fb/log.h>
|
||||
|
||||
#include <fbjni/detail/utf8.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace jni {
|
||||
|
||||
jint initialize(JavaVM* vm, std::function<void()>&& init_fn) noexcept {
|
||||
static std::once_flag flag{};
|
||||
// TODO (t7832883): DTRT when we have exception pointers
|
||||
static auto error_msg = std::string{"Failed to initialize fbjni"};
|
||||
static auto error_occured = false;
|
||||
|
||||
std::call_once(flag, [vm] {
|
||||
static bool error_occured = [vm] {
|
||||
bool retVal = false;
|
||||
try {
|
||||
Environment::initialize(vm);
|
||||
} catch (std::exception& ex) {
|
||||
error_occured = true;
|
||||
retVal = true;
|
||||
try {
|
||||
error_msg = std::string{"Failed to initialize fbjni: "} + ex.what();
|
||||
} catch (...) {
|
||||
// Ignore, we already have a fall back message
|
||||
}
|
||||
} catch (...) {
|
||||
error_occured = true;
|
||||
retVal = true;
|
||||
}
|
||||
});
|
||||
return retVal;
|
||||
}();
|
||||
|
||||
try {
|
||||
if (error_occured) {
|
||||
@@ -43,7 +51,7 @@ jint initialize(JavaVM* vm, std::function<void()>&& init_fn) noexcept {
|
||||
|
||||
init_fn();
|
||||
} catch (const std::exception& e) {
|
||||
FBLOGE("error %s", e.what());
|
||||
FBJNI_LOGE("error %s", e.what());
|
||||
translatePendingCppExceptionToJavaException();
|
||||
} catch (...) {
|
||||
translatePendingCppExceptionToJavaException();
|
||||
@@ -54,19 +62,19 @@ jint initialize(JavaVM* vm, std::function<void()>&& init_fn) noexcept {
|
||||
}
|
||||
|
||||
alias_ref<JClass> findClassStatic(const char* name) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = detail::currentOrNull();
|
||||
if (!env) {
|
||||
throw std::runtime_error("Unable to retrieve JNIEnv*.");
|
||||
}
|
||||
auto cls = env->FindClass(name);
|
||||
local_ref<jclass> cls = adopt_local(env->FindClass(name));
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!cls);
|
||||
auto leaking_ref = (jclass)env->NewGlobalRef(cls);
|
||||
auto leaking_ref = (jclass)env->NewGlobalRef(cls.get());
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!leaking_ref);
|
||||
return wrap_alias(leaking_ref);
|
||||
}
|
||||
|
||||
local_ref<JClass> findClassLocal(const char* name) {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = detail::currentOrNull();
|
||||
if (!env) {
|
||||
throw std::runtime_error("Unable to retrieve JNIEnv*.");
|
||||
}
|
||||
@@ -79,17 +87,25 @@ local_ref<JClass> findClassLocal(const char* name) {
|
||||
// jstring /////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string JString::toStdString() const {
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
auto utf16String = JStringUtf16Extractor(env, self());
|
||||
auto length = env->GetStringLength(self());
|
||||
return detail::utf16toUTF8(utf16String, length);
|
||||
return detail::utf16toUTF8(utf16String.chars(), utf16String.length());
|
||||
}
|
||||
|
||||
std::u16string JString::toU16String() const {
|
||||
const auto env = Environment::current();
|
||||
auto utf16String = JStringUtf16Extractor(env, self());
|
||||
if (!utf16String.chars() || utf16String.length() == 0) {
|
||||
return {};
|
||||
}
|
||||
return std::u16string(reinterpret_cast<const char16_t*>(utf16String.chars()), utf16String.length());
|
||||
}
|
||||
|
||||
local_ref<JString> make_jstring(const char* utf8) {
|
||||
if (!utf8) {
|
||||
return {};
|
||||
}
|
||||
const auto env = internal::getEnv();
|
||||
const auto env = Environment::current();
|
||||
size_t len;
|
||||
size_t modlen = detail::modifiedLength(reinterpret_cast<const uint8_t*>(utf8), &len);
|
||||
jstring result;
|
||||
@@ -112,6 +128,18 @@ local_ref<JString> make_jstring(const char* utf8) {
|
||||
return adopt_local(result);
|
||||
}
|
||||
|
||||
local_ref<JString> make_jstring(const std::u16string& utf16) {
|
||||
if (utf16.empty()) {
|
||||
return {};
|
||||
}
|
||||
const auto env = Environment::current();
|
||||
static_assert(
|
||||
sizeof(jchar) == sizeof(std::u16string::value_type),
|
||||
"Expecting jchar to be the same size as std::u16string::CharT");
|
||||
jstring result = env->NewString(reinterpret_cast<const jchar*>(utf16.c_str()), utf16.size());
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION();
|
||||
return adopt_local(result);
|
||||
}
|
||||
|
||||
// JniPrimitiveArrayFunctions //////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -120,50 +148,44 @@ local_ref<JString> make_jstring(const char* utf8) {
|
||||
#define DEFINE_PRIMITIVE_METHODS(TYPE, NAME, SMALLNAME) \
|
||||
\
|
||||
template<> \
|
||||
FBEXPORT \
|
||||
TYPE* JPrimitiveArray<TYPE ## Array>::getElements(jboolean* isCopy) { \
|
||||
auto env = internal::getEnv(); \
|
||||
auto env = Environment::current(); \
|
||||
TYPE* res = env->Get ## NAME ## ArrayElements(self(), isCopy); \
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); \
|
||||
return res; \
|
||||
} \
|
||||
\
|
||||
template<> \
|
||||
FBEXPORT \
|
||||
void JPrimitiveArray<TYPE ## Array>::releaseElements( \
|
||||
TYPE* elements, jint mode) { \
|
||||
auto env = internal::getEnv(); \
|
||||
auto env = Environment::current(); \
|
||||
env->Release ## NAME ## ArrayElements(self(), elements, mode); \
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); \
|
||||
} \
|
||||
\
|
||||
template<> \
|
||||
FBEXPORT \
|
||||
void JPrimitiveArray<TYPE ## Array>::getRegion( \
|
||||
jsize start, jsize length, TYPE* buf) { \
|
||||
auto env = internal::getEnv(); \
|
||||
auto env = Environment::current(); \
|
||||
env->Get ## NAME ## ArrayRegion(self(), start, length, buf); \
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); \
|
||||
} \
|
||||
\
|
||||
template<> \
|
||||
FBEXPORT \
|
||||
void JPrimitiveArray<TYPE ## Array>::setRegion( \
|
||||
jsize start, jsize length, const TYPE* elements) { \
|
||||
auto env = internal::getEnv(); \
|
||||
auto env = Environment::current(); \
|
||||
env->Set ## NAME ## ArrayRegion(self(), start, length, elements); \
|
||||
FACEBOOK_JNI_THROW_PENDING_EXCEPTION(); \
|
||||
} \
|
||||
\
|
||||
FBEXPORT \
|
||||
local_ref<TYPE ## Array> make_ ## SMALLNAME ## _array(jsize size) { \
|
||||
auto array = internal::getEnv()->New ## NAME ## Array(size); \
|
||||
auto array = Environment::current()->New ## NAME ## Array(size); \
|
||||
FACEBOOK_JNI_THROW_EXCEPTION_IF(!array); \
|
||||
return adopt_local(array); \
|
||||
} \
|
||||
\
|
||||
template<> \
|
||||
FBEXPORT \
|
||||
local_ref<TYPE ## Array> JArray ## NAME::newArray(size_t count) { \
|
||||
return make_ ## SMALLNAME ## _array(count); \
|
||||
} \
|
||||
@@ -179,13 +201,37 @@ DEFINE_PRIMITIVE_METHODS(jfloat, Float, float)
|
||||
DEFINE_PRIMITIVE_METHODS(jdouble, Double, double)
|
||||
#pragma pop_macro("DEFINE_PRIMITIVE_METHODS")
|
||||
|
||||
namespace detail {
|
||||
|
||||
detail::BaseHybridClass* HybridDestructor::getNativePointer() {
|
||||
static auto pointerField = javaClassStatic()->getField<jlong>("mNativePointer");
|
||||
auto* value = reinterpret_cast<detail::BaseHybridClass*>(getFieldValue(pointerField));
|
||||
if (!value) {
|
||||
throwNewJavaException("java/lang/NullPointerException", "java.lang.NullPointerException");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void HybridDestructor::setNativePointer(
|
||||
std::unique_ptr<detail::BaseHybridClass> new_value) {
|
||||
static auto pointerField = javaClassStatic()->getField<jlong>("mNativePointer");
|
||||
auto old_value = std::unique_ptr<detail::BaseHybridClass>(
|
||||
reinterpret_cast<detail::BaseHybridClass*>(getFieldValue(pointerField)));
|
||||
if (new_value && old_value) {
|
||||
FBJNI_LOGF("Attempt to set C++ native pointer twice");
|
||||
}
|
||||
setFieldValue(pointerField, reinterpret_cast<jlong>(new_value.release()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Internal debug /////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace internal {
|
||||
|
||||
FBEXPORT ReferenceStats g_reference_stats;
|
||||
ReferenceStats g_reference_stats;
|
||||
|
||||
FBEXPORT void facebook::jni::internal::ReferenceStats::reset() noexcept {
|
||||
void facebook::jni::internal::ReferenceStats::reset() noexcept {
|
||||
locals_deleted = globals_deleted = weaks_deleted = 0;
|
||||
}
|
||||
|
||||
32
libs/fbjni/cxx/fbjni/fbjni.h
Normal file
32
libs/fbjni/cxx/fbjni/fbjni.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <fbjni/detail/Environment.h>
|
||||
#include <fbjni/detail/Log.h>
|
||||
#include <fbjni/detail/Common.h>
|
||||
#include <fbjni/detail/Exceptions.h>
|
||||
#include <fbjni/detail/ReferenceAllocators.h>
|
||||
#include <fbjni/detail/References.h>
|
||||
#include <fbjni/detail/Meta.h>
|
||||
#include <fbjni/detail/CoreClasses.h>
|
||||
#include <fbjni/detail/Iterator.h>
|
||||
#include <fbjni/detail/Hybrid.h>
|
||||
#include <fbjni/detail/Registration.h>
|
||||
#include <fbjni/detail/JWeakReference.h>
|
||||
116
libs/fbjni/cxx/lyra/cxa_throw.cpp
Normal file
116
libs/fbjni/cxx/lyra/cxa_throw.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <atomic>
|
||||
#include <stdexcept>
|
||||
#include <cxxabi.h>
|
||||
#include <unwind.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <lyra/lyra_exceptions.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
namespace {
|
||||
std::atomic<bool> enableBacktraces{true};
|
||||
}
|
||||
|
||||
void enableCxaThrowHookBacktraces(bool enable) {
|
||||
enableBacktraces.store(enable, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
[[gnu::noreturn]] void (*original_cxa_throw)(void*, const std::type_info*, void (*) (void *));
|
||||
|
||||
#if defined(_LIBCPP_VERSION)
|
||||
[[noreturn]] void cxa_throw(void* obj, const std::type_info* type, void (*destructor) (void *)) {
|
||||
// lyra doesn't have support yet for libc++.
|
||||
original_cxa_throw(obj, type, destructor);
|
||||
}
|
||||
#else
|
||||
|
||||
using namespace detail;
|
||||
|
||||
namespace {
|
||||
|
||||
const auto traceHolderType =
|
||||
static_cast<const abi::__class_type_info*>(&typeid(ExceptionTraceHolder));
|
||||
|
||||
// lyra's __cxa_throw attaches stack trace information to thrown exceptions. It basically does:
|
||||
// 1. capture stack trace
|
||||
// 2. construct a new type_info struct that:
|
||||
// a. holds the ExceptionTraceHolder
|
||||
// b. supports upcasting to lyra::ExceptionTraceHolder* (by just returning the holder member)
|
||||
// c. acts like the original exception type_info otherwise
|
||||
// 3. call original __cxa_throw() with original exception pointer, the
|
||||
// HijackedExceptionTypeInfo, and HijackedExceptionTypeInfo::destructor
|
||||
// (which will both delete the constructed type info and call the original
|
||||
// destructor).
|
||||
struct HijackedExceptionTypeInfo : public abi::__class_type_info {
|
||||
HijackedExceptionTypeInfo(void* obj, const std::type_info* base, void(*destructor)(void*))
|
||||
: abi::__class_type_info{base->name()}, base_{base}, orig_dest_{destructor} {
|
||||
}
|
||||
|
||||
bool __is_pointer_p() const override {
|
||||
return base_->__is_pointer_p();
|
||||
}
|
||||
|
||||
bool __is_function_p() const override {
|
||||
return base_->__is_function_p();
|
||||
}
|
||||
|
||||
bool __do_catch(const type_info *__thr_type, void **__thr_obj, unsigned __outer) const override {
|
||||
return base_->__do_catch(__thr_type, __thr_obj, __outer);
|
||||
}
|
||||
|
||||
bool __do_upcast(const abi::__class_type_info *__target, void **__obj_ptr) const override {
|
||||
if (__target == traceHolderType) {
|
||||
*__obj_ptr = (void*)&stack_;
|
||||
return true;
|
||||
}
|
||||
return base_->__do_upcast(__target, __obj_ptr);
|
||||
}
|
||||
|
||||
static void destructor(void* obj) {
|
||||
auto exc_ptr = reinterpret_cast<std::exception_ptr*>(&obj);
|
||||
auto info = reinterpret_cast<const::std::type_info*>(exc_ptr->__cxa_exception_type());
|
||||
auto mutable_info = static_cast<HijackedExceptionTypeInfo*>(const_cast<std::type_info*>(info));
|
||||
mutable_info->orig_dest_(obj);
|
||||
delete mutable_info;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::type_info* base_;
|
||||
void (*orig_dest_)(void*);
|
||||
ExceptionTraceHolder stack_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
[[noreturn]] void cxa_throw(void* obj, const std::type_info* type, void (*destructor) (void *)) {
|
||||
if (enableBacktraces.load(std::memory_order_relaxed)) {
|
||||
if (!type->__do_upcast(traceHolderType, &obj)) {
|
||||
type = new HijackedExceptionTypeInfo(obj, type, destructor);
|
||||
destructor = HijackedExceptionTypeInfo::destructor;
|
||||
}
|
||||
}
|
||||
original_cxa_throw(obj, type, destructor);
|
||||
}
|
||||
|
||||
#endif // libc++
|
||||
|
||||
} // namespace lyra
|
||||
} // namespace facebook
|
||||
@@ -1,19 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2004-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <fb/lyra.h>
|
||||
|
||||
#include <lyra/lyra.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <ios>
|
||||
#include <ostream>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <unwind.h>
|
||||
|
||||
#include <fbjni/detail/Log.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace facebook {
|
||||
@@ -68,6 +82,27 @@ void captureBacktrace(size_t skip, vector<InstructionPointer>& stackTrace) {
|
||||
BacktraceState state = {skip, stackTrace};
|
||||
_Unwind_Backtrace(unwindCallback, &state);
|
||||
}
|
||||
|
||||
// this is a pointer to a function
|
||||
std::atomic<LibraryIdentifierFunctionType> gLibraryIdentifierFunction{nullptr};
|
||||
|
||||
}
|
||||
|
||||
void setLibraryIdentifierFunction(LibraryIdentifierFunctionType func) {
|
||||
gLibraryIdentifierFunction.store(func, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::string StackTraceElement::buildId() const {
|
||||
if (!hasBuildId_) {
|
||||
auto getBuildId = gLibraryIdentifierFunction.load(std::memory_order_relaxed);
|
||||
if (getBuildId) {
|
||||
buildId_ = getBuildId(libraryName());
|
||||
} else {
|
||||
buildId_ = "<unimplemented>";
|
||||
}
|
||||
hasBuildId_ = true;
|
||||
}
|
||||
return buildId_;
|
||||
}
|
||||
|
||||
void getStackTrace(vector<InstructionPointer>& stackTrace, size_t skip) {
|
||||
@@ -94,7 +129,6 @@ void getStackTraceSymbols(vector<StackTraceElement>& symbols,
|
||||
ostream& operator<<(ostream& out, const StackTraceElement& elm) {
|
||||
IosFlagsSaver flags{out};
|
||||
|
||||
// TODO(t10748683): Add build id to the output
|
||||
out << "{dso=" << elm.libraryName() << " offset=" << hex
|
||||
<< showbase << elm.libraryOffset();
|
||||
|
||||
@@ -102,7 +136,7 @@ ostream& operator<<(ostream& out, const StackTraceElement& elm) {
|
||||
out << " func=" << elm.functionName() << "()+" << elm.functionOffset();
|
||||
}
|
||||
|
||||
out << " build-id=" << hex << setw(8) << 0
|
||||
out << " build-id=" << hex << setw(8) << elm.buildId()
|
||||
<< "}";
|
||||
|
||||
return out;
|
||||
@@ -121,5 +155,28 @@ ostream& operator<<(ostream& out, const vector<StackTraceElement>& trace) {
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void logStackTrace(const vector<StackTraceElement>& trace) {
|
||||
auto i = 0;
|
||||
FBJNI_LOGE("Backtrace:");
|
||||
for (auto& elm : trace) {
|
||||
if (!elm.functionName().empty()) {
|
||||
FBJNI_LOGE(" #%02d |lyra|{dso=%s offset=%#x func=%s+%#x build-id=%s}",
|
||||
i++,
|
||||
elm.libraryName().c_str(),
|
||||
elm.libraryOffset(),
|
||||
elm.functionName().c_str(),
|
||||
elm.functionOffset(),
|
||||
elm.buildId().c_str());
|
||||
} else {
|
||||
FBJNI_LOGE(" #%02d |lyra|{dso=%s offset=%#x build-id=%s}",
|
||||
i++,
|
||||
elm.libraryName().c_str(),
|
||||
elm.libraryOffset(),
|
||||
elm.buildId().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2004-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <fb/visibility.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
@@ -21,17 +27,21 @@ constexpr size_t kDefaultLimit = 64;
|
||||
|
||||
using InstructionPointer = const void*;
|
||||
|
||||
class FBEXPORT StackTraceElement {
|
||||
class StackTraceElement {
|
||||
public:
|
||||
StackTraceElement(InstructionPointer absoluteProgramCounter,
|
||||
InstructionPointer libraryBase,
|
||||
InstructionPointer functionAddress, std::string libraryName,
|
||||
InstructionPointer functionAddress,
|
||||
std::string libraryName,
|
||||
std::string functionName)
|
||||
: absoluteProgramCounter_{absoluteProgramCounter},
|
||||
libraryBase_{libraryBase},
|
||||
functionAddress_{functionAddress},
|
||||
libraryName_{std::move(libraryName)},
|
||||
functionName_{std::move(functionName)} {}
|
||||
functionName_{std::move(functionName)},
|
||||
hasBuildId_{false},
|
||||
buildId_{}
|
||||
{}
|
||||
|
||||
InstructionPointer libraryBase() const noexcept { return libraryBase_; }
|
||||
|
||||
@@ -68,14 +78,28 @@ class FBEXPORT StackTraceElement {
|
||||
return absoluteabsoluteProgramCounter - absoluteSymbol;
|
||||
}
|
||||
|
||||
std::string buildId() const;
|
||||
private:
|
||||
const InstructionPointer absoluteProgramCounter_;
|
||||
const InstructionPointer libraryBase_;
|
||||
const InstructionPointer functionAddress_;
|
||||
const std::string libraryName_;
|
||||
const std::string functionName_;
|
||||
|
||||
mutable bool hasBuildId_;
|
||||
mutable std::string buildId_;
|
||||
};
|
||||
|
||||
/**
|
||||
* If a library identifier function is set, it is passed a libraryName
|
||||
* for the frame, and returns a library build id string, which will be
|
||||
* included in the logged stack trace. The most common use for this
|
||||
* will be correlating stack traces with breakpad identifiers.
|
||||
*/
|
||||
typedef std::string (*LibraryIdentifierFunctionType)(const std::string&);
|
||||
|
||||
void setLibraryIdentifierFunction(LibraryIdentifierFunctionType func);
|
||||
|
||||
/**
|
||||
* Populate the vector with the current stack trace
|
||||
*
|
||||
@@ -92,8 +116,7 @@ class FBEXPORT StackTraceElement {
|
||||
*
|
||||
* @param skip The number of frames to skip before capturing the trace
|
||||
*/
|
||||
FBEXPORT void getStackTrace(std::vector<InstructionPointer>& stackTrace,
|
||||
size_t skip = 0);
|
||||
void getStackTrace(std::vector<InstructionPointer>& stackTrace, size_t skip = 0);
|
||||
|
||||
/**
|
||||
* Creates a vector and populates it with the current stack trace
|
||||
@@ -109,7 +132,7 @@ FBEXPORT void getStackTrace(std::vector<InstructionPointer>& stackTrace,
|
||||
*
|
||||
* @limit The maximum number of frames captured
|
||||
*/
|
||||
FBEXPORT inline std::vector<InstructionPointer> getStackTrace(
|
||||
inline std::vector<InstructionPointer> getStackTrace(
|
||||
size_t skip = 0,
|
||||
size_t limit = kDefaultLimit) {
|
||||
auto stackTrace = std::vector<InstructionPointer>{};
|
||||
@@ -126,7 +149,7 @@ FBEXPORT inline std::vector<InstructionPointer> getStackTrace(
|
||||
*
|
||||
* @param stackTrace The input stack trace
|
||||
*/
|
||||
FBEXPORT void getStackTraceSymbols(std::vector<StackTraceElement>& symbols,
|
||||
void getStackTraceSymbols(std::vector<StackTraceElement>& symbols,
|
||||
const std::vector<InstructionPointer>& trace);
|
||||
|
||||
/**
|
||||
@@ -134,7 +157,7 @@ FBEXPORT void getStackTraceSymbols(std::vector<StackTraceElement>& symbols,
|
||||
*
|
||||
* @param stackTrace The input stack trace
|
||||
*/
|
||||
FBEXPORT inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
const std::vector<InstructionPointer>& trace) {
|
||||
auto symbols = std::vector<StackTraceElement>{};
|
||||
getStackTraceSymbols(symbols, trace);
|
||||
@@ -153,7 +176,7 @@ FBEXPORT inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
*
|
||||
* @param limit The maximum number of frames captured
|
||||
*/
|
||||
FBEXPORT inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
size_t skip = 0,
|
||||
size_t limit = kDefaultLimit) {
|
||||
return getStackTraceSymbols(getStackTrace(skip + 1, limit));
|
||||
@@ -162,12 +185,21 @@ FBEXPORT inline std::vector<StackTraceElement> getStackTraceSymbols(
|
||||
/**
|
||||
* Formatting a stack trace element
|
||||
*/
|
||||
FBEXPORT std::ostream& operator<<(std::ostream& out, const StackTraceElement& elm);
|
||||
std::ostream& operator<<(std::ostream& out, const StackTraceElement& elm);
|
||||
|
||||
/**
|
||||
* Formatting a stack trace
|
||||
*/
|
||||
FBEXPORT std::ostream& operator<<(std::ostream& out,
|
||||
std::ostream& operator<<(std::ostream& out,
|
||||
const std::vector<StackTraceElement>& trace);
|
||||
|
||||
/**
|
||||
* Log stack trace
|
||||
*
|
||||
* Makes it possible to log a trace without using a temporary stream when the
|
||||
* underlying log API is not stream based.
|
||||
*/
|
||||
void logStackTrace(const std::vector<StackTraceElement>& trace);
|
||||
|
||||
}
|
||||
}
|
||||
32
libs/fbjni/cxx/lyra/lyra_breakpad.cpp
Normal file
32
libs/fbjni/cxx/lyra/lyra_breakpad.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <lyra/lyra.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
/**
|
||||
* This can be overridden by an implementation capable of looking up
|
||||
* the breakpad id for logging purposes.
|
||||
*/
|
||||
__attribute__((weak))
|
||||
std::string getBreakpadId(const std::string& library) {
|
||||
return "<unimplemented>";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
98
libs/fbjni/cxx/lyra/lyra_exceptions.cpp
Normal file
98
libs/fbjni/cxx/lyra/lyra_exceptions.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <lyra/lyra_exceptions.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <typeinfo>
|
||||
|
||||
#include <fbjni/detail/Log.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
using namespace detail;
|
||||
|
||||
namespace {
|
||||
std::terminate_handler gTerminateHandler;
|
||||
|
||||
const ExceptionTraceHolder* getExceptionTraceHolder(std::exception_ptr ptr) {
|
||||
try {
|
||||
std::rethrow_exception(ptr);
|
||||
} catch (const ExceptionTraceHolder& holder) {
|
||||
return &holder;
|
||||
} catch (...) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void logExceptionAndAbort() {
|
||||
if (auto ptr = std::current_exception()) {
|
||||
FBJNI_LOGE("Uncaught exception: %s", toString(ptr).c_str());
|
||||
auto trace = getExceptionTraceHolder(ptr);
|
||||
if (trace) {
|
||||
logStackTrace(getStackTraceSymbols(trace->stackTrace_));
|
||||
}
|
||||
}
|
||||
if (gTerminateHandler) {
|
||||
gTerminateHandler();
|
||||
} else {
|
||||
FBJNI_LOGF("Uncaught exception and no gTerminateHandler set");
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<InstructionPointer> emptyTrace;
|
||||
} // namespace
|
||||
|
||||
ExceptionTraceHolder::~ExceptionTraceHolder() {}
|
||||
|
||||
detail::ExceptionTraceHolder::ExceptionTraceHolder() {
|
||||
// TODO(cjhopman): This should be done more safely (i.e. use preallocated space, etc.).
|
||||
stackTrace_.reserve(128);
|
||||
getStackTrace(stackTrace_, 1);
|
||||
}
|
||||
|
||||
|
||||
void ensureRegisteredTerminateHandler() {
|
||||
static auto initializer = (gTerminateHandler = std::set_terminate(logExceptionAndAbort));
|
||||
(void)initializer;
|
||||
}
|
||||
|
||||
const std::vector<InstructionPointer>& getExceptionTrace(std::exception_ptr ptr) {
|
||||
auto holder = getExceptionTraceHolder(ptr);
|
||||
return holder ? holder->stackTrace_ : emptyTrace;
|
||||
}
|
||||
|
||||
std::string toString(std::exception_ptr ptr) {
|
||||
if (!ptr) {
|
||||
return "No exception";
|
||||
}
|
||||
|
||||
try {
|
||||
std::rethrow_exception(ptr);
|
||||
} catch (std::exception& e) {
|
||||
std::stringstream ss;
|
||||
ss << typeid(e).name() << ": " << e.what();
|
||||
return ss.str();
|
||||
} catch (...) {
|
||||
return "Unknown exception";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
94
libs/fbjni/cxx/lyra/lyra_exceptions.h
Normal file
94
libs/fbjni/cxx/lyra/lyra_exceptions.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <exception>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include <lyra/lyra.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace lyra {
|
||||
|
||||
namespace detail {
|
||||
struct ExceptionTraceHolder {
|
||||
ExceptionTraceHolder();
|
||||
// Need some virtual function to make this a polymorphic type.
|
||||
virtual ~ExceptionTraceHolder();
|
||||
ExceptionTraceHolder(const ExceptionTraceHolder&) = delete;
|
||||
ExceptionTraceHolder(ExceptionTraceHolder&&) = default;
|
||||
|
||||
std::vector<InstructionPointer> stackTrace_;
|
||||
};
|
||||
|
||||
template <typename E, bool hasTraceHolder>
|
||||
struct Holder : E, ExceptionTraceHolder {
|
||||
Holder(E&& e) : E{std::forward<E>(e)}, ExceptionTraceHolder{} {}
|
||||
};
|
||||
template <typename E>
|
||||
struct Holder<E, true> : E {
|
||||
Holder(E&& e) : E{std::forward<E>(e)} {}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the stack trace of an exception
|
||||
*/
|
||||
const std::vector<InstructionPointer>& getExceptionTrace(std::exception_ptr ptr);
|
||||
|
||||
/**
|
||||
* Throw an exception and store the stack trace. This works like
|
||||
* std::throw_with_nested in that it will actually throw a type that is
|
||||
* publicly derived from both E and detail::ExceptionTraceHolder.
|
||||
*/
|
||||
template <class E>
|
||||
[[noreturn]] void fbthrow(E&& exception) {
|
||||
throw detail::Holder<E, std::is_base_of<detail::ExceptionTraceHolder, E>::value>{std::forward<E>(exception)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a terminate handler that logs traces is installed.
|
||||
* setLibraryIdentifierFunction should be called first if the stack
|
||||
* trace should log build ids for libraries.
|
||||
*/
|
||||
void ensureRegisteredTerminateHandler();
|
||||
|
||||
/**
|
||||
* Helper to convert an exception to a string
|
||||
*/
|
||||
std::string toString(std::exception_ptr exceptionPointer);
|
||||
|
||||
/**
|
||||
* lyra's cxa_throw will delegate to the original cxa throw. That pointer must
|
||||
* be set before lyra::cxa_throw is called.
|
||||
*
|
||||
* One example use would be to statically compile against something that overrides __cxa_throw.
|
||||
* That would look something like:
|
||||
*
|
||||
* [[noreturn]] void __cxa_throw(void* obj, const std::type_info* type, void (*destructor) (void*)) {
|
||||
* static auto initializer = lyra::original_cxa_throw = lookupOriginalCxaThrow();
|
||||
* lyra::cxa_throw(obj, type, destructor);
|
||||
* }
|
||||
*/
|
||||
[[gnu::noreturn]] extern void (*original_cxa_throw)(void*, const std::type_info*, void (*) (void*));
|
||||
[[noreturn]] void cxa_throw(void* obj, const std::type_info* type, void (*destructor) (void *));
|
||||
|
||||
void enableCxaThrowHookBacktraces(bool enable);
|
||||
|
||||
}
|
||||
}
|
||||
27
libs/fbjni/java/com/facebook/jni/CppException.java
Normal file
27
libs/fbjni/java/com/facebook/jni/CppException.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
|
||||
@DoNotStrip
|
||||
public class CppException extends RuntimeException {
|
||||
@DoNotStrip
|
||||
public CppException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
|
||||
@DoNotStrip
|
||||
public class CppSystemErrorException extends CppException {
|
||||
int errorCode;
|
||||
|
||||
@DoNotStrip
|
||||
public CppSystemErrorException(String message, int errorCode) {
|
||||
super(message);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
148
libs/fbjni/java/com/facebook/jni/DestructorThread.java
Normal file
148
libs/fbjni/java/com/facebook/jni/DestructorThread.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* A thread which invokes the "destruct" routine for objects after they have been garbage collected.
|
||||
*
|
||||
* <p>An object which needs to be destructed should create a static subclass of {@link Destructor}.
|
||||
* Once the referent object is garbage collected, the DestructorThread will callback to the {@link
|
||||
* Destructor#destruct()} method.
|
||||
*
|
||||
* <p>The underlying thread in DestructorThread starts when the first Destructor is constructed and
|
||||
* then runs indefinitely.
|
||||
*/
|
||||
public class DestructorThread {
|
||||
|
||||
/**
|
||||
* N.B The Destructor <b>SHOULD NOT</b> refer back to its referent object either explicitly or
|
||||
* implicitly (for example, as a non-static inner class). This will create a reference cycle where
|
||||
* the referent object will never be garbage collected.
|
||||
*/
|
||||
public abstract static class Destructor extends PhantomReference<Object> {
|
||||
|
||||
private Destructor next;
|
||||
private Destructor previous;
|
||||
|
||||
Destructor(Object referent) {
|
||||
super(referent, sReferenceQueue);
|
||||
sDestructorStack.push(this);
|
||||
}
|
||||
|
||||
private Destructor() {
|
||||
super(null, sReferenceQueue);
|
||||
}
|
||||
|
||||
/** Callback which is invoked when the original object has been garbage collected. */
|
||||
abstract void destruct();
|
||||
}
|
||||
|
||||
/** A list to keep all active Destructors in memory confined to the Destructor thread. */
|
||||
private static DestructorList sDestructorList;
|
||||
/** A thread safe stack where new Destructors are placed before being add to sDestructorList. */
|
||||
private static DestructorStack sDestructorStack;
|
||||
|
||||
private static ReferenceQueue sReferenceQueue;
|
||||
private static Thread sThread;
|
||||
|
||||
static {
|
||||
sDestructorStack = new DestructorStack();
|
||||
sReferenceQueue = new ReferenceQueue();
|
||||
sDestructorList = new DestructorList();
|
||||
sThread =
|
||||
new Thread("HybridData DestructorThread") {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try {
|
||||
Destructor current = (Destructor) sReferenceQueue.remove();
|
||||
current.destruct();
|
||||
|
||||
// If current is in the sDestructorStack,
|
||||
// transfer all the Destructors in the stack to the list.
|
||||
if (current.previous == null) {
|
||||
sDestructorStack.transferAllToList();
|
||||
}
|
||||
|
||||
DestructorList.drop(current);
|
||||
} catch (InterruptedException e) {
|
||||
// Continue. This thread should never be terminated.
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sThread.start();
|
||||
}
|
||||
|
||||
private static class Terminus extends Destructor {
|
||||
@Override
|
||||
void destruct() {
|
||||
throw new IllegalStateException("Cannot destroy Terminus Destructor.");
|
||||
}
|
||||
}
|
||||
|
||||
/** This is a thread safe, lock-free Treiber-like Stack of Destructors. */
|
||||
private static class DestructorStack {
|
||||
private AtomicReference<Destructor> mHead = new AtomicReference<>();
|
||||
|
||||
public void push(Destructor newHead) {
|
||||
Destructor oldHead;
|
||||
do {
|
||||
oldHead = mHead.get();
|
||||
newHead.next = oldHead;
|
||||
} while (!mHead.compareAndSet(oldHead, newHead));
|
||||
}
|
||||
|
||||
public void transferAllToList() {
|
||||
Destructor current = mHead.getAndSet(null);
|
||||
while (current != null) {
|
||||
Destructor next = current.next;
|
||||
sDestructorList.enqueue(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A doubly-linked list of Destructors. */
|
||||
private static class DestructorList {
|
||||
private Destructor mHead;
|
||||
|
||||
public DestructorList() {
|
||||
mHead = new Terminus();
|
||||
mHead.next = new Terminus();
|
||||
mHead.next.previous = mHead;
|
||||
}
|
||||
|
||||
public void enqueue(Destructor current) {
|
||||
current.next = mHead.next;
|
||||
mHead.next = current;
|
||||
|
||||
current.next.previous = current;
|
||||
current.previous = mHead;
|
||||
}
|
||||
|
||||
private static void drop(Destructor current) {
|
||||
current.next.previous = current.previous;
|
||||
current.previous.next = current.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
22
libs/fbjni/java/com/facebook/jni/HybridClassBase.java
Normal file
22
libs/fbjni/java/com/facebook/jni/HybridClassBase.java
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
|
||||
@DoNotStrip
|
||||
public abstract class HybridClassBase extends HybridData {}
|
||||
87
libs/fbjni/java/com/facebook/jni/HybridData.java
Normal file
87
libs/fbjni/java/com/facebook/jni/HybridData.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
/**
|
||||
* This object holds a native C++ member for hybrid Java/C++ objects.
|
||||
*
|
||||
* <p>NB: THREAD SAFETY
|
||||
*
|
||||
* <p>{@link #resetNative} deletes the corresponding native object synchronously on whatever thread
|
||||
* the method is called on. Otherwise, deletion will occur on the {@link DestructorThread} thread.
|
||||
*/
|
||||
@DoNotStrip
|
||||
public class HybridData {
|
||||
|
||||
static {
|
||||
SoLoader.loadLibrary("sonarfb");
|
||||
}
|
||||
|
||||
@DoNotStrip private Destructor mDestructor = new Destructor(this);
|
||||
|
||||
/**
|
||||
* To explicitly delete the instance, call resetNative(). If the C++ instance is referenced after
|
||||
* this is called, a NullPointerException will be thrown. resetNative() may be called multiple
|
||||
* times safely. Because the {@link DestructorThread} also calls resetNative, the instance will
|
||||
* not leak if this is not called, but timing of deletion and the thread the C++ dtor is called on
|
||||
* will be at the whim of the Java GC. If you want to control the thread and timing of the
|
||||
* destructor, you should call resetNative() explicitly.
|
||||
*/
|
||||
public synchronized void resetNative() {
|
||||
mDestructor.destruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* N.B. Thread safety. If you call isValid from a different thread than {@link #resetNative()}
|
||||
* then be sure to do so while synchronizing on the hybrid. For example:
|
||||
*
|
||||
* <pre><code>
|
||||
* synchronized(hybrid) {
|
||||
* if (hybrid.isValid) {
|
||||
* // Do stuff.
|
||||
* }
|
||||
* }
|
||||
* </code></pre>
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return mDestructor.mNativePointer != 0;
|
||||
}
|
||||
|
||||
public static class Destructor extends DestructorThread.Destructor {
|
||||
|
||||
// Private C++ instance
|
||||
@DoNotStrip private long mNativePointer;
|
||||
|
||||
Destructor(Object referent) {
|
||||
super(referent);
|
||||
}
|
||||
|
||||
@Override
|
||||
void destruct() {
|
||||
// When invoked from the DestructorThread instead of resetNative,
|
||||
// the DestructorThread has exclusive ownership of the HybridData
|
||||
// so synchronization is not necessary.
|
||||
deleteNative(mNativePointer);
|
||||
mNativePointer = 0;
|
||||
}
|
||||
|
||||
static native void deleteNative(long pointer);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
import java.util.Iterator;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
31
libs/fbjni/java/com/facebook/jni/NativeRunnable.java
Normal file
31
libs/fbjni/java/com/facebook/jni/NativeRunnable.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
|
||||
/** A Runnable that has a native run implementation. */
|
||||
@DoNotStrip
|
||||
public class NativeRunnable implements Runnable {
|
||||
|
||||
private final HybridData mHybridData;
|
||||
|
||||
private NativeRunnable(HybridData hybridData) {
|
||||
mHybridData = hybridData;
|
||||
}
|
||||
|
||||
public native void run();
|
||||
}
|
||||
36
libs/fbjni/java/com/facebook/jni/ThreadScopeSupport.java
Normal file
36
libs/fbjni/java/com/facebook/jni/ThreadScopeSupport.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
@DoNotStrip
|
||||
public class ThreadScopeSupport {
|
||||
static {
|
||||
SoLoader.loadLibrary("sonarfb");
|
||||
}
|
||||
|
||||
// This is just used for ThreadScope::withClassLoader to have a java function
|
||||
// in the stack so that jni has access to the correct classloader.
|
||||
@DoNotStrip
|
||||
private static void runStdFunction(long ptr) {
|
||||
runStdFunctionImpl(ptr);
|
||||
}
|
||||
|
||||
private static native void runStdFunctionImpl(long ptr);
|
||||
}
|
||||
32
libs/fbjni/java/com/facebook/jni/UnknownCppException.java
Normal file
32
libs/fbjni/java/com/facebook/jni/UnknownCppException.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2018-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni;
|
||||
|
||||
import com.facebook.jni.annotations.DoNotStrip;
|
||||
|
||||
@DoNotStrip
|
||||
public class UnknownCppException extends CppException {
|
||||
@DoNotStrip
|
||||
public UnknownCppException() {
|
||||
super("Unknown");
|
||||
}
|
||||
|
||||
@DoNotStrip
|
||||
public UnknownCppException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
33
libs/fbjni/java/com/facebook/jni/annotations/DoNotStrip.java
Normal file
33
libs/fbjni/java/com/facebook/jni/annotations/DoNotStrip.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright 2004-present, Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.facebook.jni.annotations;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Add this annotation to a class, method, or field to instruct Proguard to not strip it out.
|
||||
*
|
||||
* This is useful for methods called via reflection that could appear as unused to Proguard.
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
|
||||
@Retention(CLASS)
|
||||
public @interface DoNotStrip {
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user