首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

当从C++创建JVM时,从JAVA调用本机方法?

基础概念

在Java中,本地方法(Native Method)是指那些用非Java语言(如C、C++)编写的方法。这些方法可以通过Java Native Interface (JNI) 与Java代码进行交互。JNI允许Java代码调用本地方法,同时也允许本地方法调用Java代码。

相关优势

  1. 性能提升:对于一些计算密集型或I/O密集型的任务,使用C/C++编写的本地方法通常比纯Java代码执行得更快。
  2. 系统级访问:本地方法可以直接访问操作系统底层资源,这在Java中是受限的。
  3. 库集成:可以利用现有的C/C++库,而这些库可能已经经过了优化和广泛测试。

类型

  1. 静态注册:在Java类中声明本地方法,并在编译时通过javah工具生成C/C++头文件,然后在C/C++代码中实现这些方法。
  2. 动态注册:在运行时通过JNI函数RegisterNatives动态注册本地方法。

应用场景

  1. 性能敏感的应用:如游戏、图形处理、大数据处理等。
  2. 系统级编程:如操作系统插件、硬件驱动等。
  3. 集成现有库:如图像处理库、加密库等。

从C++创建JVM并调用Java方法

以下是一个简单的示例,展示如何在C++中创建JVM并调用Java方法:

Java代码

代码语言:txt
复制
public class HelloWorld {
    public native void printHello();

    static {
        System.loadLibrary("HelloWorldImpl");
    }

    public static void main(String[] args) {
        new HelloWorld().printHello();
    }
}

C++代码

代码语言:txt
复制
#include <jni.h>
#include <iostream>

extern "C" JNIEXPORT void JNICALL Java_HelloWorld_printHello(JNIEnv *env, jobject obj) {
    std::cout << "Hello from C++!" << std::endl;
}

int main(int argc, char **argv) {
    JavaVM *jvm;
    JNIEnv *env;
    JavaVMInitArgs vm_args;
    JavaVMOption options[1];

    options[0].optionString = "-Djava.class.path=./";
    vm_args.version = JNI_VERSION_1_8;
    vm_args.nOptions = 1;
    vm_args.options = options;
    vm_args.ignoreUnrecognized = JNI_FALSE;

    // Create the JVM
    jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
    if (res != JNI_OK) {
        std::cerr << "Failed to create JVM" << std::endl;
        return -1;
    }

    // Load the Java class
    jclass cls = env->FindClass("HelloWorld");
    if (cls == nullptr) {
        std::cerr << "Failed to find class" << std::endl;
        jvm->DestroyJavaVM();
        return -1;
    }

    // Find the main method
    jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
    if (mid == nullptr) {
        std::cerr << "Failed to find main method" << std::endl;
        jvm->DestroyJavaVM();
        return -1;
    }

    // Call the main method
    env->CallStaticVoidMethod(cls, mid, nullptr);

    // Destroy the JVM
    jvm->DestroyJavaVM();

    return 0;
}

编译和运行

  1. 编译Java代码并生成头文件:
  2. 编译Java代码并生成头文件:
  3. 编译C++代码:
  4. 编译C++代码:
  5. 运行C++程序:
  6. 运行C++程序:

可能遇到的问题及解决方法

  1. 找不到类或方法
    • 确保Java类路径正确。
    • 确保类名和方法签名正确。
  • JVM创建失败
    • 检查JDK路径和版本是否正确。
    • 确保JNI库路径正确。
  • 内存泄漏
    • 确保在使用完JVM后调用DestroyJavaVM释放资源。

通过以上步骤,你可以在C++中创建JVM并调用Java方法。更多详细信息和示例代码,可以参考Java Native Interface Specification

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Spring杂谈 | 桥接方法JVM方法调用

” 在上面我们探究什么时候会出现桥接方法,应该能感觉到,桥接方法的出现都是要满足下面两个条件才会出现 子类重写了父类的方法 子类中进行重写的方法跟父类不一致(参数不一致或者返回值不一致) 满足了上面两个条件...,编译器会自动为我生成桥接方法,因为编译的后文件是交由JVM执行的,生成的这个桥接方法肯定就是为了JVM进行方法调用时服务的,我们不妨大胆猜测,在这种情况下,是因为JVM在进行方法调用时,没有办法满足我们的运行时多态...要弄清楚这个问题,我们还是要从JVM方法调用说起。 JVM是怎么调用方法的? 我们应该知道,JVM要执行一个方法必定需要先找到那个方法,对计算机而言,就是要定位到方法所在的内存地址。...如果大家感兴趣的话,推荐阅读周志明老师的《深入理解Java虚拟机》 ” 字节码分析 接下来我们就通过一段字节码的分析来看看JVM到底是如何调用方法的,这里就以我们前文中第一个例子中的代码来进行分析。...桥接方法到底桥接的什么?其实就是编译器对JVMJAVA的一个桥接,编译器为了满足JAVA的重写的语义,生成了一个方法描述符与父类一致的方法,然后又调用了真实的我们定义的逻辑。

1.6K20

JVM 入门到放弃之 Java 对象创建过程

完成上述流程,其实已经完成了虚拟机中内存的创建,但是我们在 Java 执行 new创建对象的角度才刚刚开始,我们还需要调用构造方法初始化对象(可能还需要在此前后调用父类的构造方法、初始化块等)。...进行 Java 对象的初始化。即在 .class 的角度是调用 ()方法。...如果构造方法中还有调用别的方法,那么别的方法也会被执行,构造方法内的所有关联的方法都执行完毕后,才真正算是完成了 Java 对象的创建。...整体对象创建流程如下: 对象内存分配 对象内存分配过程如下图所示: 为对象分配空间的任务实质上是 Jvm 的内存区域中,指定一块确定大小的内存块给 Java 对象。(默认是在堆上分配)。...锁获取是无竞争JVM 使用原子操作而不是 OS 互斥,这种技术称为轻量级锁定。在轻量级锁定的情况下,JVM 通过 CAS 操作在对象的 Mark Word 中设置指向锁记录的指针。

57110
  • java编程——jvm角度看懂类初始化、方法重写、重载

    使用new这个关键字实例化对象、读取或者设置一个类的静态字段,以及调用一个类的静态方法时会触发类的初始化(注意,被final修饰的静态字段除外)。   2....当初始化一个类,如果其父类还没有进行过初始化,则会先触发其父类。   4. 虚拟机启动,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。   5....#22;//调用run()方法 20: aload_2 ;压入栈顶 21: invokevirtual #22;//调用run()方法 24: return   解释一下这段字节码:   0-15行的作用是创建...17和21是run()方法调用指令。   指令可以看出,这两条方法调用指令是完全一样的。可是最终执行的目标方法却并不相同。这是为啥?   ...所以虽然指令的调用是相同的,但17行调用run方法,此时栈顶存放的对象引用是Dog,21行则是Lion。   这,就是java语言中方法重写的本质。

    49930

    Java 代码如何运行聊到 JVM 和对象的创建-分配-定位-布局-垃圾回收

    ,用于存储局部变量表,操作数栈,动态链接,方法返回地址等信息 某方法调用另一个方法是通过动态链接在常量池中查询方法的引用,进而完成方法调用方法调用另一个方法的过程,即是一个栈帧在虚拟机中的入栈到出栈的过程...虚拟机中的方法入栈的顺序和方法调用顺序是一致的 详细情况请查看下图,一目了然: 对于 JVM 中虚拟机栈参数的设置 -Xss :用于设置栈的大小,栈的大小决定了方法调用的深度。...1)对象的创建 先在虚拟机栈创建栈帧,栈帧内创建对象的引用,在方法区进行类的加载,然后去 Java 堆区进行分配内存并内存初始化,再回到栈帧中初始化对象的数据,完成对象的创建。...,用于记录那些内存可用于分配,需要给对象分配内存区域,寻找一块足够大的内存空间分配给对象,并更新记录表,这种分配内存的方法叫做空闲列表法。...输出时间戳 -XX:+PrintGCDateStamps # GC日志输出指定文件中 -Xloggc:/log/gc.log 小结 Java 代码如何运行的,聊到 JVM 内存布局,虚拟机参数的配置说明

    2.8K20

    JVM内存管理的角度谈谈静态方法和静态属性 和 java对象引用与JVM自动内存管理

    试着JVM的内存管理原理的角度来谈一下静态方法和静态属性的问题,不对的地方请指正。...其实调用每个非static方法Java编译器都会自动的先加上当前调用方法对象的参数,有时候在一个方法调用另一个方法,这时可以不用在前面加上this的,因为要传递的对象参数就是当前执行这个方法的对象...这是因为静态方法直接跟class相关,调用方法的时候是类直接调用的,而不是对象,所以Java编译器就没有对象参数可以传递,这样,如果你在静态方法内部调用非静态方法,那么Java编译器怎么判断这个非静态方法是哪个对象调用的...在这种程序中,应用Java对象引用API可以创建这样一个环境,即堆内存以最小程度运行时,内存管理器创建对象。当用户返回,应用程序就会重新载入已经创建的图片。...内存管理器发现只有phantom references,对象就将处于等候phantom reference状态,应用程序向引用队列发出通知,然后对虚引用对象调用clear()方法,将其引用域设置为null

    89931

    Java线程的创建和管理,如何工作以及与操作系统的原生线程交互

    Java线程的创建和管理在Java中,可以使用Thread类来创建线程,Java线程的创建步骤如下:定义一个线程类,继承Thread类或实现Runnable接口实现run()方法,该方法中定义线程的执行逻辑创建线程对象...一个Java应用程序启动JVM创建主线程,该线程会main方法开始执行。除了主线程之外,应用程序还可以创建和管理其他线程。线程是独立运行的执行单元,可以在同一个应用程序中并发地执行多个任务。...Java线程通过调用对象的start()方法创建并启动。在调用start()方法后,JVM会为该线程分配内存空间,并在栈中创建一个新的帧用于该线程的方法调用。...然后,JVM调用线程的run()方法,在这个方法中定义了线程要执行的任务。线程被创建和启动后,JVM会根据可用的处理器核心数量来决定线程的执行顺序和调度策略。这取决于JVM的实现和操作系统的支持。...JNI允许Java程序调用使用C或C++编写的本机方法,从而与操作系统的低级功能进行交互。Java线程需要进行底层操作,可以通过JNI调用本机方法来与操作系统的原生线程交互。

    34141

    你真的会用JNI吗?这些小技巧99%的人都不知道

    这些调用是否提供对数组的直接访问,还是返回数组的副本,Java规范将其留给具体JVM版本实现。例如,JVM以不连续存储它们的方式优化数组,它可能会返回一个副本。   ...但是,对于JNI,本地代码必须通过一个或多个JNI调用返回到JVM,以获取所需的每个字段的值。这些调用会增加额外的开销,因为本机代码到Java代码的转换比普通方法调用效率更低下。...Java代码调用本地代码,本机调用Java代码的成本明显高于普通的Java方法调用。此外,转换也可能会影响JVM优化代码执行的能力。...Java代码执行时,这些异常会导致执行流程发生改变,从而自动调用异常处理代码。本地调用JNI方法,可能引发异常,这时候需要本地去检查异常,并采取适当的操作。...本地方法返回,它不仅没有被释放,而且应用程序再也没有办法获取它的引用以便以后释放它,因此该对象将永远存在。

    1.1K20

    巴拿马项目:打通 JVM 与 Native 代码

    项目概述 巴拿马项目旨在为 JVM 和用其他语言(如 C/C++)编写的本机代码之间搭建桥梁。...链接器 技术角度来看,链接器是两个二进制接口之间的桥梁:JVM 和 C/C++ 本机代码,也称为 C ABI。...链接器提供一组方法来执行向下调用和向上调用,其中: downcall 是从高级子系统发起的事件。在我们的例子中是 JVM 到较低级别的子系统,如操作系统内核或者一些 Java 代码调用一些本机代码。...要执行向下调用,需要提供调用的(本机)函数的描述符、通过符号查找分配的本机地址,以及用于创建调用本机函数的方法句柄对应的链接器。...使用外部函数和内存 API Java 调用本机代码需要解决几个问题: 获取本机库及其对应的头文件。 在 Java 中构建函数描述符 ( FunctionDescriptor )。

    62410

    Java中的堆栈和堆内存

    JVM内存的典型五个部分包括:方法区域、堆、堆栈、PC寄存器和本机内存。 现在让我们关注堆栈和堆部分。内存不像一张白纸,程序员只需记下数据就可以存储数据。相反,内存需要在使用之前进行结构化。...一些数据区域依赖于JVM,这意味着,它们是在JVM启动创建的,并且在JVM的整个生命周期中继续存在。但是,还有其他数据区域是每个线程创建和销毁的。JVM可以同时执行多个执行线程。...可以使用JVM参数-Xss更改堆栈内存的默认大小。有时,如果分配了太多变量,或者某个方法递归调用自己,堆栈可能会溢出。...所有Java程序员都知道的一个常见错误是Java.lang.StackOverFlowError。堆栈变满,会弹出此错误。Java中的每个方法调用都会在堆栈中创建一个新块。...因此,设计糟糕的递归方法调用很容易耗尽所有堆栈,从而导致溢出错误。 什么是Java中的堆内存 堆是一个内存区域,它在JVM启动创建,并一直存在,直到JVM被销毁。

    1.2K10

    BAT面试必问题系列:深入详解JVM 内存区域及内存溢出分析

    前言 在JVM的管控下,Java程序员不再需要管理内存的分配与释放,这和在C和C++的世界是完全不一样的。所以,在JVM的帮助下,Java程序员很少会关注内存泄露和内存溢出的问题。...2、堆内存 堆内存主要用于存放对象和数组,它是JVM管理的内存中最大的一块区域,堆内存和方法区都被所有线程共享,在虚拟机启动创建。...一个栈帧就对应 Java 代码中的一个方法线程执行到一个方法,就代表这个方法对应的栈帧已经进入虚拟机栈并且处于栈顶的位置,每一个 Java 方法调用到执行结束,就对应了一个栈帧入栈到出栈的过程...二、JVM 内存溢出 1、堆内存溢出 堆内存中主要存放对象、数组等,只要不断地创建这些对象,并且保证 GC Roots 到对象之间有可达路径来避免垃圾收集回收机制清除这些对象,这些对象所占空间超过最大堆容量...4、本机直接内存溢出 本机直接内存(DirectMemory)并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域,但 Java 中用到 NIO 相关操作(比如 ByteBuffer

    72080

    JVM体系结构的解释

    对于每个方法调用,将在堆栈存储器中创建一个条目,称为堆栈帧。将在堆栈内存中创建所有局部变量。堆栈区域是线程安全的,因为它不是共享资源。...本机方法栈-本机方法堆栈保存本机方法信息。对于每个线程,将创建一个单独的本机方法堆栈。 3.执行引擎 分配给运行时数据区的字节码将由执行引擎执行。执行引擎读取字节码并逐个执行。 1....解释器的缺点是,一个方法被多次调用时,每次需要新的解释。 2. JIT编译器 -  JIT编译器中和了解释器的缺点。...执行引擎将使用解释器的帮助来转换字节代码,但是它找到重复的代码,它使用JIT编译器,它编译整个字节码并将其更改为本机代码。此本机代码将直接用于重复的方法调用,从而提高系统的性能。...可以通过调用“System.gc()”来触发垃圾收集,但不保证执行。JVM的垃圾收集创建的对象。 Java原生接口(JNI): JNI将与本机方法库交互,并提供执行引擎所需的本机库。

    71520

    JVM体系结构详解

    每个JVM也仅有一个堆。由于方法区和堆被多个线程共享内存,因此存储的数据不是线程安全的。 栈–每个线程将创建一个单独的运行时栈。每个方法调用都会在栈内存中生成一个条目,称为栈帧。...本地方法栈 – 本机方法栈保存着本地方法信息。对于每个线程,都将创建一个单独的本机方法栈。 3. 执行引擎 被分配给运行时数据区的字节码将由执行引擎执行。执行引擎读取字节码并逐个执行。...解释器的缺点是,一个方法被多次调用时,每次都需要一个新的解释。 JIT编译器 – JIT编译器消除了解释器的缺点。...执行引擎将在转换字节码使用解释器的帮助,但是它发现重复的代码,它使用JIT编译器,JIT编译整个字节码并将其更改为本机代码。此本机代码将直接用于重复的方法调用,从而提高系统的性能。...可以通过调用 System.gc()触发垃圾收集,但不能保证执行。JVM的垃圾收集收集创建的对象。 Java本地接口(JNI): JNI将与本地方法库交互,并提供执行引擎所需的本地库。

    52020

    JVM内存模型

    常量池是 JVM 的数据区域之一,它存储有关类的元数据,例如方法的名称、它们的参数……类在 JVM 中加载,这部分会进入常量池。...如果超过此限制,JVM 将抛出OutOfMemoryError。 方法方法区是所有 Java 虚拟机线程之间共享的内存。它是在虚拟机启动创建的,并由类加载器字节码加载。...Java虚拟机在方法调用时使用局部变量来传递参数,被调用方法的数组是调用方法的操作数栈中创建的。 运行时常量池引用:引用当前正在执行的方法的**当前类**的常量池。...Java 虚拟机堆栈存储帧。每次调用方法都会创建一个新框架并将其放入堆栈中。框架在其方法调用完成被销毁,无论该完成是正常的还是突然的(它会引发未捕获的异常)。...本机方法堆栈(每线程) 这是用 Java 以外的语言编写并通过 JNI(Java 本地接口)调用的本地代码的堆栈。由于它是“本机”堆栈,因此该堆栈的行为完全取决于底层操作系统。

    81040

    JVM架构介绍

    对于每个方法调用,都会在堆栈内存中生成一个条目,称为 Stack Frame。所有本地变量都将在堆栈内存中创建。堆栈区域是线程安全的,因为它不是共享资源。...解释器的缺点是,一个方法被多次调用时,每次都需要一个新的解释。 JIT Compiler(编译器) – JIT编译器消除了解释器的缺点。...执行引擎将在转换字节码使用解释器的帮助,但是它发现重复的代码,它使用JIT编译器,JIT编译整个字节码并将其更改为本机代码。此本机代码将直接用于重复的方法调用,从而提高系统的性能。...可以通过调用System.gc()触发垃圾收集,但不能保证执行。JVM的垃圾收集收集创建的对象。...Java Native Interface (JNI): JNI将与本机方法库进行交互,并提供执行引擎所需的本机库。 Native Method Libraries: 这是执行引擎所需的本地库的集合。

    81810

    一图读懂JVM架构解析

    类加载器子系统 Java的动态类加载功能由类加载器子系统处理,处理过程包括加载和链接,并在类文件运行时,首次引用类就开始实例化类文件,而不是在编译进行。...对于每个方法调用,将在堆栈存储器中产生一个条目,称为堆栈帧。所有局部变量将在堆栈内存中创建。堆栈区域是线程安全的,因为它不共享资源。...解释器的缺点是一个方法调用多次,每次都需要一个新的解释; (2) JIT编译器:JIT编译器消除了解释器的缺点。...执行引擎将在转换字节码使用解释器的帮助,但是它发现重复的代码,将使用JIT编译器,它编译整个字节码并将其更改为本地代码。这个本地代码将直接用于重复的方法调用,这提高了系统的性能。...可以通过调用“System.gc()”触发垃圾收集,但不能保证执行。JVM的垃圾回收对象是已创建的对象。 Java本机接口(JNI):JNI将与本机方法库进行交互,并提供执行引擎所需的本机库。

    1.5K80

    Java编程思想第五版精粹(五)-初始化和清理(中)

    1.2 工作原理 GC准备回收,首先会调用 finalize() 方法,并在下一轮的gc发生,才会真正回收对象占用的内存。...Java 没有析构器或类似概念,必须得自己手动创建一个普通方法完成清理。 例如,对象在创建的过程中会将自己绘制到屏幕。如果不明确地屏幕上将其擦除,它可能永远得不到清理。...如果在 finalize() 方法中加入某种擦除功能,那么GC,finalize() 方法调用(不保证一定会发生),图像就会被擦除,要是GC没发生,图像仍会保留下来。...如果对象是用 new 创建的(似于 Java 中),那么SE调用 C++ 的 delete 操作符Java 中不存在),就会调用相应的析构函数。...如果JVM并未面临内存耗尽的情形,它可能不会浪费时间执行gc。 1.5 终结条件 不要指望 finalize() ,必须创建其他的"清理"方法,并显式调用

    50041

    JVM-01Java内存区域与内存溢出异常(上)【运行时区域数据】

    ---- 概述 在内存管理领域 ,C/C++内存管理由开发人员管理,既拥有每一个对象的所有权,还必须负责维护每一个对象生命开始到终结的责任 对于Java开发人员来讲,在虚拟机自动内存管理机制的帮助下...因为native方法java通过JNI直接调用本地C/C++库,由于该方法是通过C/C++而不是java进行实现。...在方法运行的阶段是不会改变局部变量表的大小的。 方法调用时,创建栈帧,并压入虚拟机栈;方法执行完毕,栈帧出栈并被销毁 ---- 特性 虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈。...无法找到足够大的连续空间分配给新创建的较大对象也会提前触发一次MajorGC进行垃圾回收腾出空间。...方法区也称Non-Heap(非堆),目的是与Java堆区分开来,可通过-XX:MaxPermSize设置内存大小。 JVM运行时区域内存模型来看,堆和方法区是两块独立的内存块。

    36640

    Java虚拟机JVM架构解析

    类装载子系统 Java的动态类装载功能由类装载子系统来实现。它可以装载,链接,还有当它在运行时(而不是编译)第一次引用类,进行初始化类文件。 1.1 装载 这个组件功能是加载类。...对于每个方法调用,将在堆栈内存中创建一个条目,称为堆栈帧(Stack Frame)。所有本地变量都将在栈内存中创建。栈区域是线程安全的,因为它不是共享资源。...解释器的缺点是,一个方法被多次调用时,每次都需要新的解释。 JIT Compiler – JIT编译器消除了解释器的缺点。...执行引擎将使用解释器的帮助来转换字节代码,但是它发现重复的代码,它使用JIT编译器,它编译整个字节码并将其更改为本机代码。这种本机代码将直接用于重复的方法调用,从而提高系统的性能。...可以通过调用“System.gc()”来触发垃圾收集,但不会立即执行(执行时机由GC决定)。JVM的垃圾回收收集已创建的对象。

    60120

    Spring6 AOT 提前编译

    GraalVM 提供两种运行 Java 应用程序的方法:在 HotSpot JVM 上使用 Graal 即时 (JIT) 编译器或作为提前 (AOT) 编译的本机可执行文件。...1.3、Native Image目前业界除了这种在JVM中进行AOT的方案,还有另外一种实现Java AOT的思路,那就是直接摒弃JVM,和C/C++一样通过编译器直接将代码编译成机器代码,然后运行。...它通过C语言实现了一个超微缩的运行时组件 —— Substrate VM,基本实现了JVM的各种特性,但足够轻量、可以被轻松内嵌,这就让Java语言和工程摆脱JVM的限制,能够真正意义上实现和C/C++...在构建本机可执行文件期间处理的 Java 字节码包括所有应用程序类、依赖项、第三方依赖库和任何所需的 JDK 类。生成的自包含本机可执行文件特定于不需要 JVM 的每个单独的操作系统和机器体系结构。...相比于使用JVM运行,Native Image的速度要快上不少,cpu占用也更低一些,官方提供的各类实验数据也可以看出Native Image对于启动速度和内存占用带来的提升是非常显著的:图片图片

    30320

    什么是本地方法

    如果本地方法栈可以动态扩展,并且在尝试扩展的时候无法申请到足够的内存,或者在创建新的线程没有足够的内存去创建对应的本地方法栈,那么Java虚拟机将会抛出一个outofMemoryError 异常。...某个线程在调用一个本地方法,就进入了一个全新且不再受虚拟机限制的领域,其和虚拟机拥有同样的权限。...Native 方法Native 方法Java 通过 JNI 直接调用本地 C/C++ 库,Native 方法相当于 C/C++ 暴露给 Java 的一个接口,Java 通过这个接口调用 C/C++...线程调用 Java 方法,虚拟机会创建一个栈帧并且压入 Java 虚拟机栈。...然而调用的是 native 方法,虚拟机会保持 Java 虚拟机栈不变,也不会向 Java 虚拟机栈中压入新栈帧,虚拟机只是简单的动态连接并且直接调用指定的 native 方法

    11100
    领券