1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 /** @file CoreClasses.h 20 * 21 * In CoreClasses.h wrappers for the core classes (jobject, jclass, and jstring) 22 * is defined to provide access to corresponding JNI functions + some 23 * conveniance. 24 */ 25 26 #include "Meta-forward.h" 27 #include "References-forward.h" 28 #include "TypeTraits.h" 29 30 #include <memory> 31 32 #include <jni.h> 33 34 #include <fbjni/detail/SimpleFixedString.h> 35 36 namespace facebook { 37 namespace jni { 38 39 class JClass; 40 class JObject; 41 class JString; 42 43 namespace detail { 44 45 /// Lookup a class by name. This should only be used internally. 46 jclass findClass(JNIEnv* env, const char* name); 47 48 } // namespace detail 49 50 /// Lookup a class by name. Note this functions returns an alias_ref that 51 /// points to a leaked global reference. This is appropriate for classes 52 /// that are never unloaded (which is any class in an Android app and most 53 /// Java programs). 54 /// 55 /// The most common use case for this is storing the result 56 /// in a "static auto" variable, or a static global. 57 /// 58 /// @return Returns a leaked global reference to the class 59 alias_ref<JClass> findClassStatic(const char* name); 60 61 /// Lookup a class by name. Note this functions returns a local reference, 62 /// which means that it must not be stored in a static variable. 63 /// 64 /// The most common use case for this is one-time initialization 65 /// (like caching method ids). 66 /// 67 /// @return Returns a global reference to the class 68 local_ref<JClass> findClassLocal(const char* name); 69 70 /// Check to see if two references refer to the same object. Comparison with 71 /// nullptr returns true if and only if compared to another nullptr. A weak 72 /// reference that refers to a reclaimed object count as nullptr. 73 bool isSameObject(alias_ref<JObject> lhs, alias_ref<JObject> rhs) noexcept; 74 75 // Together, these classes allow convenient use of any class with the fbjni 76 // helpers. To use: 77 // 78 // struct MyClass : public JavaClass<MyClass> { 79 // constexpr static auto kJavaDescriptor = "Lcom/example/package/MyClass;"; 80 // }; 81 // 82 // Then, an alias_ref<MyClass> will be backed by an instance of MyClass. 83 // JavaClass provides a convenient way to add functionality to these 84 // smart references. 85 // 86 // For example: 87 // 88 // struct MyClass : public JavaClass<MyClass> { 89 // constexpr static auto kJavaDescriptor = "Lcom/example/package/MyClass;"; 90 // 91 // void foo() { 92 // static const auto method = javaClassStatic()->getMethod<void()>("foo"); 93 // method(self()); 94 // } 95 // 96 // static local_ref<javaobject> create(int i) { 97 // return newInstance(i); 98 // } 99 // }; 100 // 101 // auto obj = MyClass::create(10); 102 // obj->foo(); 103 // 104 // While users of a JavaClass-type can lookup methods and fields through the 105 // underlying JClass, those calls can only be checked at runtime. It is 106 // recommended that the JavaClass-type instead explicitly expose it's methods as 107 // in the example above. 108 109 namespace detail { 110 template <typename JC, typename... Args> 111 static local_ref<JC> newInstance(Args... args); 112 } 113 114 class MonitorLock; 115 116 class JObject : detail::JObjectBase { 117 public: 118 static constexpr auto kJavaDescriptor = "Ljava/lang/Object;"; 119 120 static constexpr detail::SimpleFixedString<0> get_instantiated_java_descriptor()121 get_instantiated_java_descriptor() { 122 return ""; 123 } get_instantiated_base_name()124 static constexpr detail::SimpleFixedString<0> get_instantiated_base_name() { 125 return ""; 126 } 127 128 /// Get a @ref local_ref of the object's class 129 local_ref<JClass> getClass() const noexcept; 130 131 /// Checks if the object is an instance of a class 132 bool isInstanceOf(alias_ref<JClass> cls) const noexcept; 133 134 /// Get the primitive value of a field 135 template <typename T> 136 T getFieldValue(JField<T> field) const noexcept; 137 138 /// Get and wrap the value of a field in a @ref local_ref 139 template <typename T> 140 local_ref<T*> getFieldValue(JField<T*> field) const noexcept; 141 142 /// Set the value of field. Any Java type is accepted. 143 template <typename T> 144 void setFieldValue(JField<T> field, T value) noexcept; 145 template < 146 typename T, 147 typename = typename std::enable_if<IsPlainJniReference<T>(), T>::type> 148 void setFieldValue(JField<T> field, alias_ref<T> value) noexcept; 149 150 /// Convenience method to create a std::string representing the object 151 std::string toString() const; 152 153 // Take this object's monitor lock 154 MonitorLock lock() const noexcept; 155 156 typedef _jobject _javaobject; 157 typedef _javaobject* javaobject; 158 159 protected: 160 jobject self() const noexcept; 161 162 private: 163 friend void swap(JObject& a, JObject& b) noexcept; 164 template <typename> 165 friend struct detail::ReprAccess; 166 template <typename, typename, typename> 167 friend class JavaClass; 168 }; 169 170 namespace detail { 171 template <typename, typename Base, typename JType> 172 struct JTypeFor { 173 static_assert( 174 std::is_base_of< 175 std::remove_pointer<jobject>::type, 176 typename std::remove_pointer<JType>::type>::value, 177 ""); 178 using _javaobject = typename std::remove_pointer<JType>::type; 179 using javaobject = JType; 180 }; 181 182 template <typename T, typename Base> 183 struct JTypeFor<T, Base, void> { 184 // JNI pattern for jobject assignable pointer 185 struct _javaobject : Base::_javaobject { 186 // This allows us to map back to the defining type (in ReprType, for 187 // example). 188 typedef T JniRefRepr; 189 }; 190 using javaobject = _javaobject*; 191 }; 192 } // namespace detail 193 194 // JavaClass provides a method to inform fbjni about user-defined Java types. 195 // Given a class: 196 // struct Foo : JavaClass<Foo> { 197 // static constexpr auto kJavaDescriptor = "Lcom/example/package/Foo;"; 198 // }; 199 // fbjni can determine the java type/method signatures for Foo::javaobject and 200 // smart refs (like alias_ref<Foo>) will hold an instance of Foo 201 // and provide access to it through the -> and * operators. 202 // 203 // The "Base" template argument can be used to specify the JavaClass superclass 204 // of this type (for instance, JString's Base is JObject). 205 // 206 // The "JType" template argument is used to provide a jni type (like jstring, 207 // jthrowable) to be used as javaobject. This should only be necessary for 208 // built-in jni types and not user-defined ones. 209 template <typename T, typename Base = JObject, typename JType = void> 210 class JavaClass : public Base { 211 using JObjType = typename detail::JTypeFor<T, Base, JType>; 212 213 public: 214 using _javaobject = typename JObjType::_javaobject; 215 using javaobject = typename JObjType::javaobject; 216 217 using JavaBase = JavaClass; 218 219 static alias_ref<JClass> javaClassStatic(); 220 static local_ref<JClass> javaClassLocal(); 221 222 protected: 223 /// Allocates a new object and invokes the specified constructor 224 /// Like JClass's getConstructor, this function can only check at runtime if 225 /// the class actually has a constructor that accepts the corresponding types. 226 /// While a JavaClass-type can expose this function directly, it is 227 /// recommended to instead to use this to explicitly only expose those 228 /// constructors that the Java class actually has (i.e. with static create() 229 /// functions). 230 template <typename... Args> 231 static local_ref<T> newInstance(Args... args) { 232 return detail::newInstance<T>(args...); 233 } 234 235 javaobject self() const noexcept; 236 }; 237 238 /// Wrapper to provide functionality to jclass references 239 class JClass : public JavaClass<JClass, JObject, jclass> { 240 public: 241 /// Java type descriptor 242 static constexpr const char* kJavaDescriptor = "Ljava/lang/Class;"; 243 244 /// Get a @local_ref to the super class of this class 245 local_ref<JClass> getSuperclass() const noexcept; 246 247 /// Register native methods for the class. Usage looks like this: 248 /// 249 /// classRef->registerNatives({ 250 /// makeNativeMethod("nativeMethodWithAutomaticDescriptor", 251 /// methodWithAutomaticDescriptor), 252 /// makeNativeMethod("nativeMethodWithExplicitDescriptor", 253 /// "(Lcom/facebook/example/MyClass;)V", 254 /// methodWithExplicitDescriptor), 255 /// makeCriticalNativeMethod_DO_NOT_USE_OR_YOU_WILL_BE_FIRED("criticalNativeMethodWithAutomaticDescriptor", 256 /// criticalNativeMethodWithAutomaticDescriptor), 257 /// makeCriticalNativeMethod_DO_NOT_USE_OR_YOU_WILL_BE_FIRED("criticalNativeMethodWithExplicitDescriptor", 258 /// "(IIF)Z", 259 /// criticalNativeMethodWithExplicitDescriptor), 260 /// }); 261 /// 262 /// By default, C++ exceptions raised will be converted to Java exceptions. 263 /// To avoid this and get the "standard" JNI behavior of a crash when a C++ 264 /// exception is crashing out of the JNI method, declare the method noexcept. 265 /// This does NOT apply to critical native methods, where exceptions causes 266 /// a crash. 267 void registerNatives(std::initializer_list<JNINativeMethod> methods); 268 269 /// Check to see if the class is assignable from another class 270 /// @pre cls != nullptr 271 bool isAssignableFrom(alias_ref<JClass> cls) const noexcept; 272 273 /// Convenience method to lookup the constructor with descriptor as specified 274 /// by the type arguments 275 template <typename F> 276 JConstructor<F> getConstructor() const; 277 278 /// Convenience method to lookup the constructor with specified descriptor 279 template <typename F> 280 JConstructor<F> getConstructor(const char* descriptor) const; 281 282 /// Look up the method with given name and descriptor as specified with the 283 /// type arguments 284 template <typename F> 285 JMethod<F> getMethod(const char* name) const; 286 287 /// Look up the method with given name and descriptor 288 template <typename F> 289 JMethod<F> getMethod(const char* name, const char* descriptor) const; 290 291 /// Lookup the field with the given name and deduced descriptor 292 template <typename T> 293 JField<PrimitiveOrJniType<T>> getField(const char* name) const; 294 295 /// Lookup the field with the given name and descriptor 296 template <typename T> 297 JField<PrimitiveOrJniType<T>> getField( 298 const char* name, 299 const char* descriptor) const; 300 301 /// Lookup the static field with the given name and deduced descriptor 302 template <typename T> 303 JStaticField<PrimitiveOrJniType<T>> getStaticField(const char* name) const; 304 305 /// Lookup the static field with the given name and descriptor 306 template <typename T> 307 JStaticField<PrimitiveOrJniType<T>> getStaticField( 308 const char* name, 309 const char* descriptor) const; 310 311 /// Get the primitive value of a static field 312 template <typename T> 313 T getStaticFieldValue(JStaticField<T> field) const noexcept; 314 315 /// Get and wrap the value of a field in a @ref local_ref 316 template <typename T> 317 local_ref<T*> getStaticFieldValue(JStaticField<T*> field) noexcept; 318 319 /// Set the value of field. Any Java type is accepted. 320 template <typename T> 321 void setStaticFieldValue(JStaticField<T> field, T value) noexcept; 322 template < 323 typename T, 324 typename = typename std::enable_if<IsPlainJniReference<T>(), T>::type> 325 void setStaticFieldValue(JStaticField<T> field, alias_ref<T> value) noexcept; 326 327 /// Allocates a new object and invokes the specified constructor 328 template <typename R, typename... Args> 329 local_ref<R> newObject(JConstructor<R(Args...)> constructor, Args... args) 330 const; 331 332 /// Look up the static method with given name and descriptor as specified with 333 /// the type arguments 334 template <typename F> 335 JStaticMethod<F> getStaticMethod(const char* name) const; 336 337 /// Look up the static method with given name and descriptor 338 template <typename F> 339 JStaticMethod<F> getStaticMethod(const char* name, const char* descriptor) 340 const; 341 342 /// Look up the non virtual method with given name and descriptor as specified 343 /// with the type arguments 344 template <typename F> 345 JNonvirtualMethod<F> getNonvirtualMethod(const char* name) const; 346 347 /// Look up the non virtual method with given name and descriptor 348 template <typename F> 349 JNonvirtualMethod<F> getNonvirtualMethod( 350 const char* name, 351 const char* descriptor) const; 352 353 /// Get the canonical name of the class 354 local_ref<JString> getCanonicalName(); 355 356 private: 357 jclass self() const noexcept; 358 }; 359 360 // Convenience method to register methods on a class without holding 361 // onto the class object. 362 void registerNatives( 363 const char* name, 364 std::initializer_list<JNINativeMethod> methods); 365 366 /// Wrapper to provide functionality to jstring references 367 class JString : public JavaClass<JString, JObject, jstring> { 368 public: 369 /// Java type descriptor 370 static constexpr const char* kJavaDescriptor = "Ljava/lang/String;"; 371 372 /// Convenience method to convert a jstring object to a std::string 373 std::string toStdString() const; 374 375 /// Convenience method to convert a jstring object to a std::u16string 376 std::u16string toU16String() const; 377 }; 378 379 /// Convenience functions to convert a const char*, std::string, or 380 /// std::u16string into a @ref local_ref to a jstring. 381 local_ref<JString> make_jstring(const char* utf8); 382 local_ref<JString> make_jstring(const std::string& utf8); 383 local_ref<JString> make_jstring(const std::u16string& utf16); 384 385 namespace detail { 386 template <typename Target> 387 class ElementProxy { 388 private: 389 Target* target_; 390 size_t idx_; 391 392 public: 393 using T = typename Target::javaentry; 394 ElementProxy(Target* target, size_t idx); 395 396 ElementProxy(const ElementProxy&) noexcept = default; 397 398 ElementProxy& operator=(const T& o); 399 400 ElementProxy& operator=(alias_ref<T>& o); 401 402 ElementProxy& operator=(alias_ref<T>&& o); 403 404 ElementProxy& operator=(const ElementProxy& o); 405 406 operator const local_ref<T>() const; 407 408 operator local_ref<T>(); 409 }; 410 } // namespace detail 411 412 namespace detail { 413 class JArray : public JavaClass<JArray, JObject, jarray> { 414 public: 415 // This cannot be used in a scope that derives a descriptor (like in a method 416 // signature). Use a more derived type instead (like JArrayInt or 417 // JArrayClass<T>). 418 static constexpr const char* kJavaDescriptor = nullptr; 419 size_t size() const noexcept; 420 }; 421 422 // This is used so that the JArrayClass<T> javaobject extends jni's 423 // jobjectArray. This class should not be used directly. A general Object[] 424 // should use JArrayClass<jobject>. 425 class JTypeArray : public JavaClass<JTypeArray, JArray, jobjectArray> { 426 // This cannot be used in a scope that derives a descriptor (like in a method 427 // signature). 428 static constexpr const char* kJavaDescriptor = nullptr; 429 }; 430 } // namespace detail 431 432 template <typename T> 433 class JArrayClass : public JavaClass<JArrayClass<T>, detail::JTypeArray> { 434 public: 435 static_assert( 436 IsPlainJniReference<JniType<T>>(), 437 "Element type must be a JNI reference or JavaClass type."); 438 // javaentry is the jni type of an entry in the array (i.e. JObject). 439 using javaentry = T; 440 // javaobject is the jni type of the array. 441 using javaobject = 442 typename JavaClass<JArrayClass<T>, detail::JTypeArray>::javaobject; 443 static constexpr const char* kJavaDescriptor = nullptr; 444 static constexpr auto /* detail::SimpleFixedString<_> */ 445 get_instantiated_java_descriptor() { 446 return "[" + jtype_traits<T>::kDescriptor; 447 } 448 449 static constexpr auto /* detail::SimpleFixedString<_> */ 450 get_instantiated_base_name() { 451 return get_instantiated_java_descriptor(); 452 } 453 454 /// Allocate a new array from Java heap, for passing as a JNI parameter or 455 /// return value. NOTE: if using as a return value, you want to call release() 456 /// instead of get() on the smart pointer. 457 static local_ref<javaobject> newArray(size_t count); 458 459 /// Assign an object to the array. 460 /// Typically you will use the shorthand (*ref)[idx]=value; 461 void setElement(size_t idx, T value); 462 463 /// Read an object from the array. 464 /// Typically you will use the shorthand 465 /// T value = (*ref)[idx]; 466 /// If you use auto, you'll get an ElementProxy, which may need to be cast. 467 local_ref<T> getElement(size_t idx); 468 469 /// EXPERIMENTAL SUBSCRIPT SUPPORT 470 /// This implementation of [] returns a proxy object which then has a bunch of 471 /// specializations (adopt_local free function, operator= and casting 472 /// overloads on the ElementProxy) that can make code look like it is dealing 473 /// with a T rather than an obvious proxy. In particular, the proxy in this 474 /// iteration does not read a value and therefore does not create a LocalRef 475 /// until one of these other operators is used. There are certainly holes that 476 /// you may find by using idioms that haven't been tried yet. Consider 477 /// yourself warned. On the other hand, it does make for some idiomatic 478 /// assignment code; see TestBuildStringArray in fbjni_tests for some 479 /// examples. 480 detail::ElementProxy<JArrayClass> operator[](size_t idx); 481 }; 482 483 template <typename T> 484 using jtypeArray = typename JArrayClass<T>::javaobject; 485 486 template <typename T> 487 local_ref<typename JArrayClass<T>::javaobject> adopt_local_array( 488 jobjectArray ref); 489 490 template <typename Target> 491 local_ref<typename Target::javaentry> adopt_local( 492 detail::ElementProxy<Target> elementProxy) { 493 return static_cast<local_ref<typename Target::javaentry>>(elementProxy); 494 } 495 496 template <typename T, typename PinAlloc> 497 class PinnedPrimitiveArray; 498 499 template <typename T> 500 class PinnedArrayAlloc; 501 template <typename T> 502 class PinnedRegionAlloc; 503 template <typename T> 504 class PinnedCriticalAlloc; 505 506 /// Wrapper to provide functionality to jarray references. 507 /// This is an empty holder by itself. Construct a PinnedPrimitiveArray to 508 /// actually interact with the elements of the array. 509 template <typename JArrayType> 510 class JPrimitiveArray : public JavaClass< 511 JPrimitiveArray<JArrayType>, 512 detail::JArray, 513 JArrayType> { 514 static_assert(is_jni_primitive_array<JArrayType>(), ""); 515 516 public: 517 static constexpr const char* kJavaDescriptor = nullptr; 518 static constexpr auto /* detail::SimpleFixedString<_> */ 519 get_instantiated_java_descriptor() { 520 return jtype_traits<JArrayType>::kDescriptor; 521 } 522 static constexpr auto /* detail::SimpleFixedString<_> */ 523 get_instantiated_base_name() { 524 return JPrimitiveArray::get_instantiated_java_descriptor(); 525 } 526 527 using T = typename jtype_traits<JArrayType>::entry_type; 528 529 static local_ref<JArrayType> newArray(size_t count); 530 531 void getRegion(jsize start, jsize length, T* buf); 532 std::unique_ptr<T[]> getRegion(jsize start, jsize length); 533 void setRegion(jsize start, jsize length, const T* buf); 534 535 /// Returns a view of the underlying array. This will either be a "pinned" 536 /// version of the array (in which case changes to one immediately affect the 537 /// other) or a copy of the array (in which cases changes to the view will 538 /// take affect when destroyed or on calls to release()/commit()). 539 PinnedPrimitiveArray<T, PinnedArrayAlloc<T>> pin(); 540 541 /// Returns a view of part of the underlying array. A pinned region is always 542 /// backed by a copy of the region. 543 PinnedPrimitiveArray<T, PinnedRegionAlloc<T>> pinRegion( 544 jsize start, 545 jsize length); 546 547 /// Returns a view of the underlying array like pin(). However, while the pin 548 /// is held, the code is considered within a "critical region". In a critical 549 /// region, native code must not call JNI functions or make any calls that may 550 /// block on other Java threads. These restrictions make it more likely that 551 /// the view will be "pinned" rather than copied (for example, the VM may 552 /// suspend garbage collection within a critical region). 553 PinnedPrimitiveArray<T, PinnedCriticalAlloc<T>> pinCritical(); 554 555 private: 556 friend class PinnedArrayAlloc<T>; 557 T* getElements(jboolean* isCopy); 558 void releaseElements(T* elements, jint mode); 559 }; 560 561 local_ref<jbooleanArray> make_boolean_array(jsize size); 562 local_ref<jbyteArray> make_byte_array(jsize size); 563 local_ref<jcharArray> make_char_array(jsize size); 564 local_ref<jshortArray> make_short_array(jsize size); 565 local_ref<jintArray> make_int_array(jsize size); 566 local_ref<jlongArray> make_long_array(jsize size); 567 local_ref<jfloatArray> make_float_array(jsize size); 568 local_ref<jdoubleArray> make_double_array(jsize size); 569 570 using JArrayBoolean = JPrimitiveArray<jbooleanArray>; 571 using JArrayByte = JPrimitiveArray<jbyteArray>; 572 using JArrayChar = JPrimitiveArray<jcharArray>; 573 using JArrayShort = JPrimitiveArray<jshortArray>; 574 using JArrayInt = JPrimitiveArray<jintArray>; 575 using JArrayLong = JPrimitiveArray<jlongArray>; 576 using JArrayFloat = JPrimitiveArray<jfloatArray>; 577 using JArrayDouble = JPrimitiveArray<jdoubleArray>; 578 579 /// RAII class for pinned primitive arrays 580 /// This currently only supports read/write access to existing java arrays. You 581 /// can't create a primitive array this way yet. This class also pins the entire 582 /// array into memory during the lifetime of the PinnedPrimitiveArray. If you 583 /// need to unpin the array manually, call the release() or abort() functions. 584 /// During a long-running block of code, you should unpin the array as soon as 585 /// you're done with it, to avoid holding up the Java garbage collector. 586 template <typename T, typename PinAlloc> 587 class PinnedPrimitiveArray { 588 public: 589 static_assert( 590 is_jni_primitive<T>::value, 591 "PinnedPrimitiveArray requires primitive jni type."); 592 593 using ArrayType = typename jtype_traits<T>::array_type; 594 595 PinnedPrimitiveArray(PinnedPrimitiveArray&&); 596 PinnedPrimitiveArray(const PinnedPrimitiveArray&) = delete; 597 ~PinnedPrimitiveArray() noexcept; 598 599 PinnedPrimitiveArray& operator=(PinnedPrimitiveArray&&); 600 PinnedPrimitiveArray& operator=(const PinnedPrimitiveArray&) = delete; 601 602 T* get(); 603 void release(); 604 /// Unpins the array. If the array is a copy, pending changes are discarded. 605 void abort(); 606 /// If the array is a copy, copies pending changes to the underlying java 607 /// array. 608 void commit(); 609 610 bool isCopy() const noexcept; 611 612 const T& operator[](size_t index) const; 613 T& operator[](size_t index); 614 size_t size() const noexcept; 615 616 private: 617 alias_ref<ArrayType> array_; 618 size_t start_; 619 T* elements_; 620 jboolean isCopy_; 621 size_t size_; 622 623 void allocate(alias_ref<ArrayType>, jint start, jint length); 624 void releaseImpl(jint mode); 625 void clear() noexcept; 626 627 PinnedPrimitiveArray(alias_ref<ArrayType>, jint start, jint length); 628 629 friend class JPrimitiveArray<typename jtype_traits<T>::array_type>; 630 }; 631 632 struct JStackTraceElement : JavaClass<JStackTraceElement> { 633 static auto constexpr kJavaDescriptor = "Ljava/lang/StackTraceElement;"; 634 635 static local_ref<javaobject> create( 636 const std::string& declaringClass, 637 const std::string& methodName, 638 const std::string& file, 639 int line); 640 641 std::string getClassName() const; 642 std::string getMethodName() const; 643 std::string getFileName() const; 644 int getLineNumber() const; 645 }; 646 647 /// Wrapper to provide functionality to jthrowable references 648 class JThrowable : public JavaClass<JThrowable, JObject, jthrowable> { 649 public: 650 static constexpr const char* kJavaDescriptor = "Ljava/lang/Throwable;"; 651 652 using JStackTrace = JArrayClass<JStackTraceElement::javaobject>; 653 654 local_ref<JThrowable> initCause(alias_ref<JThrowable> cause); 655 local_ref<JStackTrace> getStackTrace(); 656 local_ref<JString> getMessage(); 657 void setStackTrace(alias_ref<JArrayClass<JStackTraceElement::javaobject>>); 658 }; 659 660 #pragma push_macro("PlainJniRefMap") 661 #undef PlainJniRefMap 662 #define PlainJniRefMap(rtype, jtype) \ 663 namespace detail { \ 664 template <> \ 665 struct RefReprType<jtype> { \ 666 using type = rtype; \ 667 }; \ 668 } 669 670 PlainJniRefMap(JArrayBoolean, jbooleanArray) PlainJniRefMap( 671 JArrayByte, 672 jbyteArray) PlainJniRefMap(JArrayChar, jcharArray) 673 PlainJniRefMap(JArrayShort, jshortArray) 674 PlainJniRefMap(JArrayInt, jintArray) 675 PlainJniRefMap(JArrayLong, jlongArray) 676 PlainJniRefMap(JArrayFloat, jfloatArray) 677 PlainJniRefMap(JArrayDouble, jdoubleArray) 678 PlainJniRefMap(JObject, jobject) 679 PlainJniRefMap(JClass, jclass) 680 PlainJniRefMap(JString, jstring) 681 PlainJniRefMap(JThrowable, jthrowable) 682 683 #pragma pop_macro("PlainJniRefMap") 684 685 } // namespace jni 686 } // namespace facebook 687 688 #include "CoreClasses-inl.h" 689