Migrate webrtc to stop using its own JniZero mirror classes

Bug: chromium:325408567
Change-Id: I2eb33b077148bf89223f1f69b07339fc9f2d948e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/347921
Reviewed-by: Jeremy Leconte <jleconte@google.com>
Commit-Queue: Jeremy Leconte <jleconte@google.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42151}
diff --git a/examples/androidvoip/jni/android_voip_client.cc b/examples/androidvoip/jni/android_voip_client.cc
index 6932799..5915f0a 100644
--- a/examples/androidvoip/jni/android_voip_client.cc
+++ b/examples/androidvoip/jni/android_voip_client.cc
@@ -185,7 +185,8 @@
   webrtc::ScopedJavaLocalRef<jstring> (*convert_function)(
       JNIEnv*, const std::string&) = &webrtc::NativeToJavaString;
   Java_VoipClient_onGetSupportedCodecsCompleted(
-      env_, j_voip_client_, NativeToJavaList(env_, names, convert_function));
+      env_, j_voip_client_,
+      webrtc::NativeToJavaList(env_, names, convert_function));
 }
 
 void AndroidVoipClient::GetLocalIPAddress(JNIEnv* env) {
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index 593ed36..8c04811 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -141,6 +141,7 @@
       ":video_egl_jni",
       "../../pc:libjingle_peerconnection",
       "../../rtc_base:ssl",
+      "//third_party/jni_zero",
     ]
     output_extension = "so"
   }
@@ -936,7 +937,6 @@
       "native_api/jni/class_loader.cc",
       "native_api/jni/java_types.cc",
       "native_api/jni/jvm.cc",
-      "src/jni/jni_generator_helper.cc",
       "src/jni/jni_generator_helper.h",
     ]
 
@@ -956,6 +956,7 @@
       "../../api:sequence_checker",
       "//api:array_view",
       "//rtc_base:checks",
+      "//third_party/jni_zero",
     ]
     absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
   }
@@ -1116,7 +1117,10 @@
       "src/jni/jvm.h",
     ]
 
-    deps = [ "../../rtc_base:checks" ]
+    deps = [
+      "../../rtc_base:checks",
+      "//third_party/jni_zero",
+    ]
   }
 
   rtc_library("videoframe_jni") {
diff --git a/sdk/android/instrumentationtests/loggable_test.cc b/sdk/android/instrumentationtests/loggable_test.cc
index 1a11075..304da05 100644
--- a/sdk/android/instrumentationtests/loggable_test.cc
+++ b/sdk/android/instrumentationtests/loggable_test.cc
@@ -23,7 +23,7 @@
                          jclass,
                          jstring j_message) {
   std::string message =
-      JavaToNativeString(jni, JavaParamRef<jstring>(j_message));
+      JavaToNativeString(jni, JavaParamRef<jstring>(jni, j_message));
   RTC_LOG(LS_INFO) << message;
 }
 
diff --git a/sdk/android/instrumentationtests/video_frame_buffer_test.cc b/sdk/android/instrumentationtests/video_frame_buffer_test.cc
index 686b232..d7f35df 100644
--- a/sdk/android/instrumentationtests/video_frame_buffer_test.cc
+++ b/sdk/android/instrumentationtests/video_frame_buffer_test.cc
@@ -21,7 +21,7 @@
                          JNIEnv* jni,
                          jclass,
                          jobject video_frame_buffer) {
-  const JavaParamRef<jobject> j_video_frame_buffer(video_frame_buffer);
+  const JavaParamRef<jobject> j_video_frame_buffer(jni, video_frame_buffer);
   rtc::scoped_refptr<VideoFrameBuffer> buffer =
       JavaToNativeFrameBuffer(jni, j_video_frame_buffer);
   return static_cast<jint>(buffer->type());
@@ -32,7 +32,7 @@
                          JNIEnv* jni,
                          jclass,
                          jobject i420_buffer) {
-  const JavaParamRef<jobject> j_i420_buffer(i420_buffer);
+  const JavaParamRef<jobject> j_i420_buffer(jni, i420_buffer);
   rtc::scoped_refptr<VideoFrameBuffer> buffer =
       JavaToNativeFrameBuffer(jni, j_i420_buffer);
   const I420BufferInterface* inputBuffer = buffer->GetI420();
diff --git a/sdk/android/native_api/DEPS b/sdk/android/native_api/DEPS
index 8afaebe..7da8f8c 100644
--- a/sdk/android/native_api/DEPS
+++ b/sdk/android/native_api/DEPS
@@ -2,4 +2,5 @@
   "+modules/audio_device/include/audio_device.h",
   "+modules/utility/include/jvm_android.h",
   "+system_wrappers/include",
+  "+third_party/jni_zero",
 ]
diff --git a/sdk/android/native_api/audio_device_module/audio_device_android.cc b/sdk/android/native_api/audio_device_module/audio_device_android.cc
index 6ba327a..62bedb1 100644
--- a/sdk/android/native_api/audio_device_module/audio_device_android.cc
+++ b/sdk/android/native_api/audio_device_module/audio_device_android.cc
@@ -40,7 +40,7 @@
                                jobject application_context,
                                AudioParameters* input_parameters,
                                AudioParameters* output_parameters) {
-  const JavaParamRef<jobject> j_context(application_context);
+  const JavaParamRef<jobject> j_context(env, application_context);
   const ScopedJavaLocalRef<jobject> j_audio_manager =
       jni::GetAudioManager(env, j_context);
   const int input_sample_rate = jni::GetDefaultSampleRate(env, j_audio_manager);
@@ -78,7 +78,7 @@
                                                 jobject application_context) {
   RTC_DLOG(LS_INFO) << __FUNCTION__;
   // Get default audio input/output parameters.
-  const JavaParamRef<jobject> j_context(application_context);
+  const JavaParamRef<jobject> j_context(env, application_context);
   const ScopedJavaLocalRef<jobject> j_audio_manager =
       jni::GetAudioManager(env, j_context);
   AudioParameters input_parameters;
@@ -104,7 +104,7 @@
     jobject application_context) {
   RTC_DLOG(LS_INFO) << __FUNCTION__;
   // Get default audio input/output parameters.
-  const JavaParamRef<jobject> j_context(application_context);
+  const JavaParamRef<jobject> j_context(env, application_context);
   const ScopedJavaLocalRef<jobject> j_audio_manager =
       jni::GetAudioManager(env, j_context);
   AudioParameters input_parameters;
@@ -155,7 +155,7 @@
                                                   jobject application_context) {
   RTC_DLOG(LS_INFO) << __FUNCTION__;
   // Get default audio input/output parameters.
-  const JavaParamRef<jobject> j_context(application_context);
+  const JavaParamRef<jobject> j_context(env, application_context);
   const ScopedJavaLocalRef<jobject> j_audio_manager =
       jni::GetAudioManager(env, j_context);
   AudioParameters input_parameters;
diff --git a/sdk/android/native_api/codecs/wrapper.cc b/sdk/android/native_api/codecs/wrapper.cc
index c3f2095..f3f1994 100644
--- a/sdk/android/native_api/codecs/wrapper.cc
+++ b/sdk/android/native_api/codecs/wrapper.cc
@@ -21,29 +21,29 @@
 namespace webrtc {
 
 SdpVideoFormat JavaToNativeVideoCodecInfo(JNIEnv* jni, jobject codec_info) {
-  return jni::VideoCodecInfoToSdpVideoFormat(jni,
-                                             JavaParamRef<jobject>(codec_info));
+  return jni::VideoCodecInfoToSdpVideoFormat(
+      jni, JavaParamRef<jobject>(jni, codec_info));
 }
 
 std::unique_ptr<VideoDecoderFactory> JavaToNativeVideoDecoderFactory(
     JNIEnv* jni,
     jobject decoder_factory) {
   return std::make_unique<jni::VideoDecoderFactoryWrapper>(
-      jni, JavaParamRef<jobject>(decoder_factory));
+      jni, JavaParamRef<jobject>(jni, decoder_factory));
 }
 
 std::unique_ptr<VideoEncoderFactory> JavaToNativeVideoEncoderFactory(
     JNIEnv* jni,
     jobject encoder_factory) {
   return std::make_unique<jni::VideoEncoderFactoryWrapper>(
-      jni, JavaParamRef<jobject>(encoder_factory));
+      jni, JavaParamRef<jobject>(jni, encoder_factory));
 }
 
 std::vector<VideoEncoder::ResolutionBitrateLimits>
 JavaToNativeResolutionBitrateLimits(JNIEnv* jni,
                                     const jobjectArray j_bitrate_limits_array) {
   return jni::JavaToNativeResolutionBitrateLimits(
-      jni, JavaParamRef<jobjectArray>(j_bitrate_limits_array));
+      jni, JavaParamRef<jobjectArray>(jni, j_bitrate_limits_array));
 }
 
 }  // namespace webrtc
diff --git a/sdk/android/native_api/jni/class_loader.cc b/sdk/android/native_api/jni/class_loader.cc
index 48082bd..c7d13f4 100644
--- a/sdk/android/native_api/jni/class_loader.cc
+++ b/sdk/android/native_api/jni/class_loader.cc
@@ -16,7 +16,7 @@
 #include "rtc_base/checks.h"
 #include "sdk/android/generated_native_api_jni/WebRtcClassLoader_jni.h"
 #include "sdk/android/native_api/jni/java_types.h"
-#include "sdk/android/native_api/jni/scoped_java_ref.h"
+#include "third_party/jni_zero/jni_zero.h"
 
 // Abort the process if `jni` has a Java exception pending. This macros uses the
 // comma operator to execute ExceptionDescribe and ExceptionClear ignoring their
@@ -62,11 +62,18 @@
 
 static ClassLoader* g_class_loader = nullptr;
 
+jclass GetClass(JNIEnv* env, const char* class_name, const char* unused) {
+  RTC_CHECK(g_class_loader);
+  return static_cast<jclass>(
+      g_class_loader->FindClass(env, class_name).Release());
+}
+
 }  // namespace
 
 void InitClassLoader(JNIEnv* env) {
   RTC_CHECK(g_class_loader == nullptr);
   g_class_loader = new ClassLoader(env);
+  jni_zero::SetClassResolver(&GetClass);
 }
 
 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* c_name) {
diff --git a/sdk/android/native_api/jni/java_types.cc b/sdk/android/native_api/jni/java_types.cc
index 7bc3d8f..363bd95 100644
--- a/sdk/android/native_api/jni/java_types.cc
+++ b/sdk/android/native_api/jni/java_types.cc
@@ -393,7 +393,7 @@
   if (!list.is_null()) {
     for (const JavaRef<jobject>& str : Iterable(jni, list)) {
       converted_list.push_back(JavaToStdString(
-          jni, JavaParamRef<jstring>(static_cast<jstring>(str.obj()))));
+          jni, JavaParamRef<jstring>(jni, static_cast<jstring>(str.obj()))));
     }
   }
   return converted_list;
diff --git a/sdk/android/native_api/jni/java_types.h b/sdk/android/native_api/jni/java_types.h
index 44ade0d..47b4164 100644
--- a/sdk/android/native_api/jni/java_types.h
+++ b/sdk/android/native_api/jni/java_types.h
@@ -340,7 +340,7 @@
 
 // Deprecated. Use scoped jobjects instead.
 inline std::string JavaToStdString(JNIEnv* jni, jstring j_string) {
-  return JavaToStdString(jni, JavaParamRef<jstring>(j_string));
+  return JavaToStdString(jni, JavaParamRef<jstring>(jni, j_string));
 }
 
 // Deprecated. Use JavaListToNativeVector<std::string, jstring> instead.
@@ -360,7 +360,7 @@
 // Deprecated. Use scoped jobjects instead.
 inline std::map<std::string, std::string> JavaToStdMapStrings(JNIEnv* jni,
                                                               jobject j_map) {
-  return JavaToStdMapStrings(jni, JavaParamRef<jobject>(j_map));
+  return JavaToStdMapStrings(jni, JavaParamRef<jobject>(jni, j_map));
 }
 
 }  // namespace webrtc
diff --git a/sdk/android/native_api/jni/jni_int_wrapper.h b/sdk/android/native_api/jni/jni_int_wrapper.h
index a6e68eb..4fec4cc 100644
--- a/sdk/android/native_api/jni/jni_int_wrapper.h
+++ b/sdk/android/native_api/jni/jni_int_wrapper.h
@@ -8,56 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-// Originally this class is from Chromium.
-// https://cs.chromium.org/chromium/src/base/android/jni_int_wrapper.h.
 
 #ifndef SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
 #define SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
 
-#include <jni.h>
-
-#include <cstdint>
-
-// Wrapper used to receive int when calling Java from native. The wrapper
-// disallows automatic conversion of anything besides int32_t to a jint.
-// Checking is only done in debugging builds.
-
-#ifdef NDEBUG
-
-typedef jint JniIntWrapper;
-
-// This inline is sufficiently trivial that it does not change the
-// final code generated by g++.
-inline jint as_jint(JniIntWrapper wrapper) {
-  return wrapper;
-}
-
-#else
-
-class JniIntWrapper {
- public:
-  JniIntWrapper() : i_(0) {}
-  JniIntWrapper(int32_t i) : i_(i) {}  // NOLINT(runtime/explicit)
-  explicit JniIntWrapper(const JniIntWrapper& ji) : i_(ji.i_) {}
-
-  jint as_jint() const { return i_; }
-
-  // If you get an "invokes a deleted function" error at the lines below it is
-  // because you used an implicit conversion to convert e.g. a long to an
-  // int32_t when calling Java. We disallow this. If you want a lossy
-  // conversion, please use an explicit conversion in your C++ code.
-  JniIntWrapper(uint32_t) = delete;  // NOLINT(runtime/explicit)
-  JniIntWrapper(uint64_t) = delete;  // NOLINT(runtime/explicit)
-  JniIntWrapper(int64_t) = delete;   // NOLINT(runtime/explicit)
-
- private:
-  const jint i_;
-};
-
-inline jint as_jint(const JniIntWrapper& wrapper) {
-  return wrapper.as_jint();
-}
-
-#endif  // NDEBUG
+#include "third_party/jni_zero/jni_zero.h"
 
 #endif  // SDK_ANDROID_NATIVE_API_JNI_JNI_INT_WRAPPER_H_
diff --git a/sdk/android/native_api/jni/scoped_java_ref.h b/sdk/android/native_api/jni/scoped_java_ref.h
index a2be447..cd30e52 100644
--- a/sdk/android/native_api/jni/scoped_java_ref.h
+++ b/sdk/android/native_api/jni/scoped_java_ref.h
@@ -19,200 +19,13 @@
 #include <utility>
 
 #include "sdk/android/native_api/jni/jvm.h"
+#include "third_party/jni_zero/jni_zero.h"
 
 namespace webrtc {
-
-// Generic base class for ScopedJavaLocalRef and ScopedJavaGlobalRef. Useful
-// for allowing functions to accept a reference without having to mandate
-// whether it is a local or global type.
-template <typename T>
-class JavaRef;
-
-// Template specialization of JavaRef, which acts as the base class for all
-// other JavaRef<> template types. This allows you to e.g. pass JavaRef<jstring>
-// into a function taking const JavaRef<jobject>&.
-template <>
-class JavaRef<jobject> {
- public:
-  JavaRef(const JavaRef&) = delete;
-  JavaRef& operator=(const JavaRef&) = delete;
-
-  jobject obj() const { return obj_; }
-  bool is_null() const {
-    // This is not valid for weak references. For weak references you need to
-    // use env->IsSameObject(objc_, nullptr), but that should be avoided anyway
-    // since it does not prevent the object from being freed immediately
-    // thereafter. Consequently, programmers should not use this check on weak
-    // references anyway and should first make a ScopedJavaLocalRef or
-    // ScopedJavaGlobalRef before checking if it is null.
-    return obj_ == nullptr;
-  }
-
- protected:
-  constexpr JavaRef() : obj_(nullptr) {}
-  explicit JavaRef(jobject obj) : obj_(obj) {}
-  jobject obj_;
-};
-
-template <typename T>
-class JavaRef : public JavaRef<jobject> {
- public:
-  JavaRef(const JavaRef&) = delete;
-  JavaRef& operator=(const JavaRef&) = delete;
-
-  T obj() const { return static_cast<T>(obj_); }
-
- protected:
-  JavaRef() : JavaRef<jobject>(nullptr) {}
-  explicit JavaRef(T obj) : JavaRef<jobject>(obj) {}
-};
-
-// Holds a local reference to a JNI method parameter.
-// Method parameters should not be deleted, and so this class exists purely to
-// wrap them as a JavaRef<T> in the JNI binding generator. Do not create
-// instances manually.
-template <typename T>
-class JavaParamRef : public JavaRef<T> {
- public:
-  // Assumes that `obj` is a parameter passed to a JNI method from Java.
-  // Does not assume ownership as parameters should not be deleted.
-  explicit JavaParamRef(T obj) : JavaRef<T>(obj) {}
-  JavaParamRef(JNIEnv*, T obj) : JavaRef<T>(obj) {}
-
-  JavaParamRef(const JavaParamRef&) = delete;
-  JavaParamRef& operator=(const JavaParamRef&) = delete;
-};
-
-// Holds a local reference to a Java object. The local reference is scoped
-// to the lifetime of this object.
-// Instances of this class may hold onto any JNIEnv passed into it until
-// destroyed. Therefore, since a JNIEnv is only suitable for use on a single
-// thread, objects of this class must be created, used, and destroyed, on a
-// single thread.
-// Therefore, this class should only be used as a stack-based object and from a
-// single thread. If you wish to have the reference outlive the current
-// callstack (e.g. as a class member) or you wish to pass it across threads,
-// use a ScopedJavaGlobalRef instead.
-template <typename T>
-class ScopedJavaLocalRef : public JavaRef<T> {
- public:
-  ScopedJavaLocalRef() = default;
-  ScopedJavaLocalRef(std::nullptr_t) {}  // NOLINT(runtime/explicit)
-
-  ScopedJavaLocalRef(JNIEnv* env, const JavaRef<T>& other) : env_(env) {
-    Reset(other.obj(), OwnershipPolicy::RETAIN);
-  }
-  // Allow constructing e.g. ScopedJavaLocalRef<jobject> from
-  // ScopedJavaLocalRef<jstring>.
-  template <typename G>
-  ScopedJavaLocalRef(ScopedJavaLocalRef<G>&& other) : env_(other.env()) {
-    Reset(other.Release(), OwnershipPolicy::ADOPT);
-  }
-  ScopedJavaLocalRef(const ScopedJavaLocalRef& other) : env_(other.env_) {
-    Reset(other.obj(), OwnershipPolicy::RETAIN);
-  }
-
-  // Assumes that `obj` is a reference to a Java object and takes
-  // ownership  of this  reference. This should preferably not be used
-  // outside of JNI helper functions.
-  ScopedJavaLocalRef(JNIEnv* env, T obj) : JavaRef<T>(obj), env_(env) {}
-
-  ~ScopedJavaLocalRef() {
-    if (obj_ != nullptr)
-      env_->DeleteLocalRef(obj_);
-  }
-
-  void operator=(const ScopedJavaLocalRef& other) {
-    Reset(other.obj(), OwnershipPolicy::RETAIN);
-  }
-  void operator=(ScopedJavaLocalRef&& other) {
-    Reset(other.Release(), OwnershipPolicy::ADOPT);
-  }
-
-  // Releases the reference to the caller. The caller *must* delete the
-  // reference when it is done with it. Note that calling a Java method
-  // is *not* a transfer of ownership and Release() should not be used.
-  T Release() {
-    T obj = static_cast<T>(obj_);
-    obj_ = nullptr;
-    return obj;
-  }
-
-  JNIEnv* env() const { return env_; }
-
- private:
-  using JavaRef<T>::obj_;
-
-  enum OwnershipPolicy {
-    // The scoped object takes ownership of an object by taking over an existing
-    // ownership claim.
-    ADOPT,
-    // The scoped object will retain the the object and any initial ownership is
-    // not changed.
-    RETAIN
-  };
-
-  void Reset(T obj, OwnershipPolicy policy) {
-    if (obj_ != nullptr)
-      env_->DeleteLocalRef(obj_);
-    obj_ = (obj != nullptr && policy == OwnershipPolicy::RETAIN)
-               ? env_->NewLocalRef(obj)
-               : obj;
-  }
-
-  JNIEnv* const env_ = AttachCurrentThreadIfNeeded();
-};
-
-// Holds a global reference to a Java object. The global reference is scoped
-// to the lifetime of this object. This class does not hold onto any JNIEnv*
-// passed to it, hence it is safe to use across threads (within the constraints
-// imposed by the underlying Java object that it references).
-template <typename T>
-class ScopedJavaGlobalRef : public JavaRef<T> {
- public:
-  using JavaRef<T>::obj_;
-
-  ScopedJavaGlobalRef() = default;
-  explicit constexpr ScopedJavaGlobalRef(std::nullptr_t) {}
-  ScopedJavaGlobalRef(JNIEnv* env, const JavaRef<T>& other)
-      : JavaRef<T>(static_cast<T>(env->NewGlobalRef(other.obj()))) {}
-  explicit ScopedJavaGlobalRef(const ScopedJavaLocalRef<T>& other)
-      : ScopedJavaGlobalRef(other.env(), other) {}
-  ScopedJavaGlobalRef(ScopedJavaGlobalRef&& other)
-      : JavaRef<T>(other.Release()) {}
-
-  ~ScopedJavaGlobalRef() {
-    if (obj_ != nullptr)
-      AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
-  }
-
-  ScopedJavaGlobalRef(const ScopedJavaGlobalRef&) = delete;
-  ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef&) = delete;
-
-  void operator=(const JavaRef<T>& other) {
-    JNIEnv* env = AttachCurrentThreadIfNeeded();
-    if (obj_ != nullptr) {
-      env->DeleteGlobalRef(obj_);
-    }
-    obj_ = other.is_null() ? nullptr : env->NewGlobalRef(other.obj());
-  }
-
-  void operator=(std::nullptr_t) {
-    if (obj_ != nullptr) {
-      AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
-    }
-    obj_ = nullptr;
-  }
-
-  // Releases the reference to the caller. The caller *must* delete the
-  // reference when it is done with it. Note that calling a Java method
-  // is *not* a transfer of ownership and Release() should not be used.
-  T Release() {
-    T obj = static_cast<T>(obj_);
-    obj_ = nullptr;
-    return obj;
-  }
-};
+using jni_zero::JavaParamRef;
+using jni_zero::JavaRef;
+using jni_zero::ScopedJavaGlobalRef;
+using jni_zero::ScopedJavaLocalRef;
 
 template <typename T>
 inline ScopedJavaLocalRef<T> static_java_ref_cast(JNIEnv* env,
diff --git a/sdk/android/native_api/network_monitor/network_monitor.cc b/sdk/android/native_api/network_monitor/network_monitor.cc
index 38be7fd..facbdbd 100644
--- a/sdk/android/native_api/network_monitor/network_monitor.cc
+++ b/sdk/android/native_api/network_monitor/network_monitor.cc
@@ -20,7 +20,7 @@
     JNIEnv* env,
     jobject application_context) {
   return std::make_unique<jni::AndroidNetworkMonitorFactory>(
-      env, JavaParamRef<jobject>(application_context));
+      env, JavaParamRef<jobject>(env, application_context));
 }
 
 std::unique_ptr<rtc::NetworkMonitorFactory>
diff --git a/sdk/android/native_api/video/wrapper.cc b/sdk/android/native_api/video/wrapper.cc
index 8faddc3..0115970 100644
--- a/sdk/android/native_api/video/wrapper.cc
+++ b/sdk/android/native_api/video/wrapper.cc
@@ -22,7 +22,7 @@
     JNIEnv* jni,
     jobject video_sink) {
   return std::make_unique<jni::VideoSinkWrapper>(
-      jni, JavaParamRef<jobject>(video_sink));
+      jni, JavaParamRef<jobject>(jni, video_sink));
 }
 
 ScopedJavaLocalRef<jobject> NativeToJavaVideoFrame(JNIEnv* jni,
diff --git a/sdk/android/src/jni/DEPS b/sdk/android/src/jni/DEPS
index ae33fa6..1661dda 100644
--- a/sdk/android/src/jni/DEPS
+++ b/sdk/android/src/jni/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+third_party/libyuv",
+  "+third_party/jni_zero",
   "+call/callfactoryinterface.h",
   "+common_video",
   "+logging/rtc_event_log/rtc_event_log_factory.h",
diff --git a/sdk/android/src/jni/java_i420_buffer.cc b/sdk/android/src/jni/java_i420_buffer.cc
index 95dcd66..860cdb2 100644
--- a/sdk/android/src/jni/java_i420_buffer.cc
+++ b/sdk/android/src/jni/java_i420_buffer.cc
@@ -8,6 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include "rtc_base/checks.h"
 #include "sdk/android/generated_video_jni/JavaI420Buffer_jni.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
 
diff --git a/sdk/android/src/jni/jni_generator_helper.cc b/sdk/android/src/jni/jni_generator_helper.cc
deleted file mode 100644
index dc34849..0000000
--- a/sdk/android/src/jni/jni_generator_helper.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "sdk/android/src/jni/jni_generator_helper.h"
-
-#include "sdk/android/native_api/jni/class_loader.h"
-
-namespace webrtc {
-
-// If `atomic_class_id` set, it'll return immediately. Otherwise, it will look
-// up the class and store it. If there's a race, we take care to only store one
-// global reference (and the duplicated effort will happen only once).
-jclass LazyGetClass(JNIEnv* env,
-                    const char* class_name,
-                    std::atomic<jclass>* atomic_class_id) {
-  const jclass value = std::atomic_load(atomic_class_id);
-  if (value)
-    return value;
-  webrtc::ScopedJavaGlobalRef<jclass> clazz(webrtc::GetClass(env, class_name));
-  RTC_CHECK(!clazz.is_null()) << class_name;
-  jclass cas_result = nullptr;
-  if (std::atomic_compare_exchange_strong(atomic_class_id, &cas_result,
-                                          clazz.obj())) {
-    // We sucessfully stored `clazz` in `atomic_class_id`, so we are
-    // intentionally leaking the global ref since it's now stored there.
-    return clazz.Release();
-  } else {
-    // Some other thread came before us and stored a global pointer in
-    // `atomic_class_id`. Relase our global ref and return the ref from the
-    // other thread.
-    return cas_result;
-  }
-}
-
-// If `atomic_method_id` set, it'll return immediately. Otherwise, it will look
-// up the method id and store it. If there's a race, it's ok since the values
-// are the same (and the duplicated effort will happen only once).
-template <MethodID::Type type>
-jmethodID MethodID::LazyGet(JNIEnv* env,
-                            jclass clazz,
-                            const char* method_name,
-                            const char* jni_signature,
-                            std::atomic<jmethodID>* atomic_method_id) {
-  const jmethodID value = std::atomic_load(atomic_method_id);
-  if (value)
-    return value;
-  auto get_method_ptr = type == MethodID::TYPE_STATIC
-                            ? &JNIEnv::GetStaticMethodID
-                            : &JNIEnv::GetMethodID;
-  jmethodID id = (env->*get_method_ptr)(clazz, method_name, jni_signature);
-  CHECK_EXCEPTION(env) << "error during GetMethodID: " << method_name << ", "
-                       << jni_signature;
-  RTC_CHECK(id) << method_name << ", " << jni_signature;
-  std::atomic_store(atomic_method_id, id);
-  return id;
-}
-
-// Various template instantiations.
-template jmethodID MethodID::LazyGet<MethodID::TYPE_STATIC>(
-    JNIEnv* env,
-    jclass clazz,
-    const char* method_name,
-    const char* jni_signature,
-    std::atomic<jmethodID>* atomic_method_id);
-
-template jmethodID MethodID::LazyGet<MethodID::TYPE_INSTANCE>(
-    JNIEnv* env,
-    jclass clazz,
-    const char* method_name,
-    const char* jni_signature,
-    std::atomic<jmethodID>* atomic_method_id);
-
-}  // namespace webrtc
diff --git a/sdk/android/src/jni/jni_generator_helper.h b/sdk/android/src/jni/jni_generator_helper.h
index acc54ba..f955cf9 100644
--- a/sdk/android/src/jni/jni_generator_helper.h
+++ b/sdk/android/src/jni/jni_generator_helper.h
@@ -18,15 +18,8 @@
 
 #include <atomic>
 
-#include "rtc_base/checks.h"
-#include "sdk/android/native_api/jni/jni_int_wrapper.h"
-#include "sdk/android/native_api/jni/scoped_java_ref.h"
+#include "third_party/jni_zero/jni_zero_internal.h"
 
-#define CHECK_CLAZZ(env, jcaller, clazz, ...) RTC_DCHECK(clazz);
-#define CHECK_NATIVE_PTR(env, jcaller, native_ptr, method_name, ...) \
-  RTC_DCHECK(native_ptr) << method_name;
-
-#define BASE_EXPORT
 #define JNI_REGISTRATION_EXPORT __attribute__((visibility("default")))
 
 #if defined(WEBRTC_ARCH_X86)
@@ -39,130 +32,22 @@
 #define JNI_GENERATOR_EXPORT extern "C" JNIEXPORT JNICALL
 #endif
 
-#if defined(WEBRTC_ARCH_X86)
-// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on
-// x86 - use force_align_arg_pointer to realign the stack at the JNI
-// boundary. crbug.com/655248
-#define JNI_BOUNDARY_EXPORT \
-  extern "C" __attribute__((visibility("default"), force_align_arg_pointer))
-#else
-#define JNI_BOUNDARY_EXPORT extern "C" __attribute__((visibility("default")))
-#endif
-
-#if defined(COMPONENT_BUILD)
-#define JNI_ZERO_COMPONENT_BUILD_EXPORT __attribute__((visibility("default")))
-#else
-#define JNI_ZERO_COMPONENT_BUILD_EXPORT
-#endif
-
-#define CHECK_EXCEPTION(jni)        \
-  RTC_CHECK(!jni->ExceptionCheck()) \
-      << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
-
 namespace webrtc {
-
-// This function will initialize `atomic_class_id` to contain a global ref to
-// the given class, and will return that ref on subsequent calls. The caller is
-// responsible to zero-initialize `atomic_class_id`. It's fine to
-// simultaneously call this on multiple threads referencing the same
-// `atomic_method_id`.
-jclass LazyGetClass(JNIEnv* env,
-                    const char* class_name,
-                    std::atomic<jclass>* atomic_class_id);
-
-// This class is a wrapper for JNIEnv Get(Static)MethodID.
-class MethodID {
- public:
-  enum Type {
-    TYPE_STATIC,
-    TYPE_INSTANCE,
-  };
-
-  // This function will initialize `atomic_method_id` to contain a ref to
-  // the given method, and will return that ref on subsequent calls. The caller
-  // is responsible to zero-initialize `atomic_method_id`. It's fine to
-  // simultaneously call this on multiple threads referencing the same
-  // `atomic_method_id`.
-  template <Type type>
-  static jmethodID LazyGet(JNIEnv* env,
-                           jclass clazz,
-                           const char* method_name,
-                           const char* jni_signature,
-                           std::atomic<jmethodID>* atomic_method_id);
-};
-
+using jni_zero::JavaParamRef;
+using jni_zero::JavaRef;
+using jni_zero::ScopedJavaGlobalRef;
+using jni_zero::ScopedJavaLocalRef;
 }  // namespace webrtc
 
-namespace jni_zero {
-// Re-export relevant classes into the namespaces the script expects.
-using webrtc::JavaParamRef;
-using webrtc::JavaRef;
-using webrtc::LazyGetClass;
-using webrtc::MethodID;
-using webrtc::ScopedJavaLocalRef;
-
-inline void CheckException(JNIEnv* env) {
-  CHECK_EXCEPTION(env);
-}
-
-// A 32 bit number could be an address on stack. Random 64 bit marker on the
-// stack is much less likely to be present on stack.
-constexpr uint64_t kJniStackMarkerValue = 0xbdbdef1bebcade1b;
-
-// Context about the JNI call with exception checked to be stored in stack.
-template <bool checked>
-struct BASE_EXPORT JniJavaCallContext {
- public:
-  inline JniJavaCallContext() {
-// TODO(ssid): Implement for other architectures.
-#if defined(__arm__) || defined(__aarch64__)
-    // This assumes that this method does not increment the stack pointer.
-    asm volatile("mov %0, sp" : "=r"(sp));
-#else
-    sp = 0;
-#endif
-  }
-
-  // Force no inline to reduce code size.
-  template <jni_zero::MethodID::Type type>
-  void Init(JNIEnv* env,
-            jclass clazz,
-            const char* method_name,
-            const char* jni_signature,
-            std::atomic<jmethodID>* atomic_method_id) {
-    env_ = env;
-
-    // Make sure compiler doesn't optimize out the assignment.
-    memcpy(&marker, &kJniStackMarkerValue, sizeof(kJniStackMarkerValue));
-    // Gets PC of the calling function.
-    pc = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
-
-    method_id_ = jni_zero::MethodID::LazyGet<type>(
-        env, clazz, method_name, jni_signature, atomic_method_id);
-  }
-
-  ~JniJavaCallContext() {
-    // Reset so that spurious marker finds are avoided.
-    memset(&marker, 0, sizeof(marker));
-    if (checked) {
-      jni_zero::CheckException(env_);
-    }
-  }
-
-  jmethodID method_id() { return method_id_; }
-
- private:
-  uint64_t marker;
-  uintptr_t sp;
-  uintptr_t pc;
-
-  JNIEnv* env_;
-  jmethodID method_id_;
-};
+// Re-export helpers in the old jni_generator namespace.
+// TODO(b/319078685): Remove once all uses of the jni_generator has been
+// updated.
+namespace jni_generator {
+using jni_zero::internal::kJniStackMarkerValue;
 
 // TODO(b/319078685): Remove JniJavaCallContextUnchecked once all uses of the
 // jni_generator has been updated.
-struct BASE_EXPORT JniJavaCallContextUnchecked {
+struct JniJavaCallContextUnchecked {
   inline JniJavaCallContextUnchecked() {
 // TODO(ssid): Implement for other architectures.
 #if defined(__arm__) || defined(__aarch64__)
@@ -207,7 +92,7 @@
 // TODO(b/319078685): Remove JniJavaCallContextChecked once all uses of the
 // jni_generator has been updated.
 // Context about the JNI call with exception unchecked to be stored in stack.
-struct BASE_EXPORT JniJavaCallContextChecked {
+struct JniJavaCallContextChecked {
   // Force no inline to reduce code size.
   template <jni_zero::MethodID::Type type>
   void Init(JNIEnv* env,
@@ -229,24 +114,6 @@
                   sizeof(JniJavaCallContextUnchecked),
               "Stack unwinder cannot work with structs of different sizes.");
 
-}  // namespace jni_zero
-
-namespace jni_zero {
-namespace internal {
-using jni_zero::JniJavaCallContext;
-using jni_zero::JniJavaCallContextChecked;
-using jni_zero::JniJavaCallContextUnchecked;
-using webrtc::LazyGetClass;
-}  // namespace internal
-}  // namespace jni_zero
-
-// Re-export helpers in the old jni_generator namespace.
-// TODO(b/319078685): Remove once all uses of the jni_generator has been
-// updated.
-namespace jni_generator {
-using jni_zero::JniJavaCallContext;
-using jni_zero::JniJavaCallContextChecked;
-using jni_zero::JniJavaCallContextUnchecked;
 }  // namespace jni_generator
 
 // Re-export helpers in the namespaces that the old jni_generator script
@@ -255,11 +122,11 @@
 // updated.
 namespace base {
 namespace android {
-using webrtc::JavaParamRef;
-using webrtc::JavaRef;
-using webrtc::LazyGetClass;
-using webrtc::MethodID;
-using webrtc::ScopedJavaLocalRef;
+using jni_zero::JavaParamRef;
+using jni_zero::JavaRef;
+using jni_zero::MethodID;
+using jni_zero::ScopedJavaLocalRef;
+using jni_zero::internal::LazyGetClass;
 }  // namespace android
 }  // namespace base
 #endif  // SDK_ANDROID_SRC_JNI_JNI_GENERATOR_HELPER_H_
diff --git a/sdk/android/src/jni/jvm.cc b/sdk/android/src/jni/jvm.cc
index 4cf1aa5..1a4292d 100644
--- a/sdk/android/src/jni/jvm.cc
+++ b/sdk/android/src/jni/jvm.cc
@@ -19,6 +19,7 @@
 #include <string>
 
 #include "rtc_base/checks.h"
+#include "third_party/jni_zero/jni_zero.h"
 
 namespace webrtc {
 namespace jni {
@@ -70,11 +71,18 @@
       << "pthread_key_create";
 }
 
+void HandleException(JNIEnv* env) {
+  RTC_CHECK(false) << (env->ExceptionDescribe(), env->ExceptionClear(), "");
+}
+
 jint InitGlobalJniVariables(JavaVM* jvm) {
   RTC_CHECK(!g_jvm) << "InitGlobalJniVariables!";
   g_jvm = jvm;
   RTC_CHECK(g_jvm) << "InitGlobalJniVariables handed NULL?";
 
+  jni_zero::SetExceptionHandler(&HandleException);
+  jni_zero::InitVM(jvm);
+
   RTC_CHECK(!pthread_once(&g_jni_ptr_once, &CreateJNIPtrKey)) << "pthread_once";
 
   JNIEnv* jni = nullptr;
diff --git a/sdk/android/src/jni/pc/logging.cc b/sdk/android/src/jni/pc/logging.cc
index cbfc99f..46a4b5a 100644
--- a/sdk/android/src/jni/pc/logging.cc
+++ b/sdk/android/src/jni/pc/logging.cc
@@ -50,8 +50,9 @@
                          jint j_severity,
                          jstring j_tag,
                          jstring j_message) {
-  std::string message = JavaToStdString(jni, JavaParamRef<jstring>(j_message));
-  std::string tag = JavaToStdString(jni, JavaParamRef<jstring>(j_tag));
+  std::string message =
+      JavaToStdString(jni, JavaParamRef<jstring>(jni, j_message));
+  std::string tag = JavaToStdString(jni, JavaParamRef<jstring>(jni, j_tag));
   RTC_LOG_TAG(static_cast<rtc::LoggingSeverity>(j_severity), tag.c_str())
       << message;
 }
diff --git a/sdk/android/src/jni/scoped_java_ref_counted.cc b/sdk/android/src/jni/scoped_java_ref_counted.cc
index 1df8c7a..fa3e82f 100644
--- a/sdk/android/src/jni/scoped_java_ref_counted.cc
+++ b/sdk/android/src/jni/scoped_java_ref_counted.cc
@@ -10,8 +10,13 @@
 
 #include "sdk/android/src/jni/scoped_java_ref_counted.h"
 
+#include "rtc_base/checks.h"
 #include "sdk/android/generated_base_jni/RefCounted_jni.h"
 
+#define CHECK_EXCEPTION(jni)        \
+  RTC_CHECK(!jni->ExceptionCheck()) \
+      << (jni->ExceptionDescribe(), jni->ExceptionClear(), "")
+
 namespace webrtc {
 namespace jni {