How to use @JniType annotations for ergonomic JNI. Relevant for Java files that use @NativeMethods or @CalledByNative.
This skill guides the process of replacing explicit JNI conversion logic (like
ConvertJavaStringToUTF8) with @JniType annotations in Java and corresponding
native types in C++.
third_party/jni_zero/README.chromium.md for a primer on JNI Zero.@NativeMethods or @CalledByNative) that take or return types that are
currently being explicitly converted in C++.@JniType
conversion defined, search the codebase for FromJniType or ToJniType
definitions for that C++ type:
rg -g "*.h" "\binline .*(From|To)JniType"
If a conversion exists, note the header file where it is defined; you will
need to include it from any C++ files that require the conversion.ConvertJavaStringToUTF8 -> std::stringConvertJavaStringToUTF16 -> std::u16stringJavaIntArrayToIntVector -> std::vector<int32_t>ToJavaArrayOfStrings -> std::vector<std::string>base::android::ConvertJavaStringToUTF8 -> std::stringif block that might skip
it).TRACE_EVENT macros). Moving
these to @JniType makes the conversion eager, which can impact
performance.@JniType("cpp_type") to the parameter or return type.String parameters, @JniType("std::string") automatically converts
Java null to C++ "". Prefer this over std::optional<std::string>
unless the C++ logic specifically distinguishes between null and empty.std::optional<T> if the Java parameter is
@Nullable. Always maintain @Nullable annotations.@JniType("std::vector<uint8_t>") for byte[].@Nullable in Java if the parameter can be null. For
@Nullable String, using std::optional<std::string> in C++ will map
null to std::nullopt.org.jni_zero.JniType is imported.const std::string&, std::vector<int32_t>&, base::OnceClosure).JNIEnv* env parameter used to be used,
but is no longer used after @JniType additions, it should be removed from
the C++ function signature.@NativeMethods, the caller
parameter is usually unnecessary. Remove it from Java and C++ to reduce
boilerplate._jni.h file.base/android/jni_string.h for all string conversions.third_party/jni_zero/default_conversions.h for containers
(std::vector, std::optional, base::span).base/android/callback_android.h for callback conversions.autoninja -C OUTPUT_DIR ../../path/to/foo.cc^ ../../path/to/Foo.java^ ...
OUTPUT_DIR (e.g. start with ../../)OUTPUT_DIR you must have been told it.Java: @JniType("std::string") String uuid C++:
base::Uuid::ParseLowercase(uuid_string) (incoming) or
uuid.AsLowercaseString() (outgoing).
@JniType("std::vector<...>") works for return types. C++ can return a
std::vector and it will be automatically converted to a Java array or List.
Java:
void doSomething(@JniType("base::OnceClosure") Runnable callback);
C++:
#include "base/android/callback_android.h"
void JNI_MyClass_DoSomething(base::OnceClosure callback) {
std::move(callback).Run();
}