是否可以制作一个调用 jdbc 的 Java JNI?

2023-11-29

我是 jni 的新手,并且非常困惑是否可以使用 jni 来实现我需要完成的任务。我想制作一个java api,它将使用jdbc来更新数据库,但是这个特定的api将从C++程序中调用。

所以我想我可能应该编写通过 jdbc 访问数据库的 jni 代码(这可能吗?),创建 C++ 代码并生成 dll,以便其他 C++ 程序可以调用 dll 来更新数据库。这一切可能吗?如果是这样,我如何真正在jni中调用jdbc? 如果这个dll最终做出来,Fortran也能调用它吗?

我的另一个想法是也许我应该制作一个常规的java程序来更新数据库,然后使用ikvm将java类包装到C++ dll中?

问题是我必须使用 Java 来使用 Access 数据库。我们的C++程序根本不会访问数据库,如果这个java api可以通过系统调用来访问就更好了。

或者有什么更好的方法可以做到吗?

我希望我解释得很好。我不太熟悉我在这里分配的内容,也找不到太多相关参考资料。

太感谢了!!

UPDATED:问题是并非所有计算机都安装了 C++ postgresql 驱动程序,但它们确实安装了 Java postgresql 驱动程序。我们不想强迫每个人都安装 C++ 数据库驱动程序,并且不会对这些 C++ 程序进行重大更改。因此,用 Java 来访问数据库是有意义的。基本上调用java系统服务(首选,例如dll?)/API来记录C++程序的开始时间和结束时间。 C++ 程序将生成一个“函数”调用(带传入参数和返回值)到此系统服务/Java API 来记录开始/结束时间。


我不会告诉你正确或错误的方法来完成你想做的事情。但是,如果您尝试调用 Java 代码 (JDBC.jar),那么以下内容适合您。否则请随意投反对票。

JVM.hpp:

#ifndef JVM_HPP_INCLUDED
#define JVM_HPP_INCLUDED

#include "../java/jni.h"
#include <windows.h>
#include <iostream>
#include <stdexcept>
#include <algorithm>

class Jvm
{
    private:
        JavaVM* jvm;
        JNIEnv* env;
        JavaVMInitArgs jvm_args;
        jclass systemClassLoader;

    public:
        Jvm(std::string ClassPath = ".");
        ~Jvm();

        inline JavaVM* GetJVM() const {return jvm;}
        inline JNIEnv* GetENV() const {return env;}
        inline jclass GetSystemClassLoader() const {return systemClassLoader;}
        void DestroyJVM();
        void PrintStackTrace();
        jclass DefineClass(const char* FullClassName, const void* ClassBuffer, std::uint32_t BufferLength);
        jclass DefineClass(const char* FullClassName, jobject ClassLoader, const void* ClassBuffer, std::uint32_t BufferLength);

        void RegisterNativeMethod(const char* MethodName, const char* MethodSignature, void* func_ptr);
        void RegisterNativeMethod(jobject ClassLoader, const char* MethodName, const char* MethodSignature, void* func_ptr);
        void RegisterNativeMethods(JNINativeMethod* Methods, std::uint32_t MethodCount);
        void RegisterNativeMethods(jobject ClassLoader, JNINativeMethod* Methods, std::uint32_t MethodCount);

    protected:
        void InitClassLoader();
};

#endif // JVM_HPP_INCLUDED

JVM.cpp:

#include "JVM.hpp"

Jvm::~Jvm()
{
    env->DeleteGlobalRef(this->systemClassLoader);
    jvm->DestroyJavaVM();
}

Jvm::Jvm(std::string ClassPath) : jvm(NULL), env(NULL), jvm_args(), systemClassLoader(NULL)
{
    JavaVMOption* options = new JavaVMOption[2];
    jvm_args.version = JNI_VERSION_1_6;
    JNI_GetDefaultJavaVMInitArgs(&jvm_args);
    options[0].optionString = const_cast<char*>("-Djava.compiler=NONE");
    options[1].optionString = const_cast<char*>(("-Djava.class.path=" + ClassPath).c_str());
    jvm_args.nOptions = 2;
    jvm_args.options = options;
    jvm_args.ignoreUnrecognized = false;

    if (JNI_CreateJavaVM(&jvm, reinterpret_cast<void**>(&env), &jvm_args))
    {
        delete[] options;
        throw std::runtime_error("Failed To Create JVM Instance.");
    }

    delete[] options;
}

void Jvm::InitClassLoader()
{
    if (!this->systemClassLoader)
    {
        jclass classloader = env->FindClass("Ljava/lang/ClassLoader;");
        if (!classloader)
        {
            throw std::runtime_error("Failed To find ClassLoader.");
        }

        jmethodID SystemLoaderMethod = env->GetStaticMethodID(classloader, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
        jobject loader = env->CallStaticObjectMethod(classloader, SystemLoaderMethod);
        this->systemClassLoader = reinterpret_cast<jclass>(env->NewGlobalRef(loader));
    }
}

void Jvm::PrintStackTrace()
{
    if (env->ExceptionOccurred())
    {
        env->ExceptionDescribe();
        env->ExceptionClear();
    }
}

jclass Jvm::DefineClass(const char* FullClassName, const void* ClassBuffer, std::uint32_t BufferLength)
{
    this->InitClassLoader();
    return this->DefineClass(FullClassName, this->systemClassLoader, ClassBuffer, BufferLength);
}

jclass Jvm::DefineClass(const char* FullClassName, jobject ClassLoader, const void* ClassBuffer, std::uint32_t BufferLength)
{
    return ClassLoader ? env->DefineClass(FullClassName, ClassLoader, static_cast<const jbyte*>(ClassBuffer), BufferLength) : NULL;
}

void Jvm::RegisterNativeMethod(const char* MethodName, const char* MethodSignature, void* func_ptr)
{
    JNINativeMethod method;
    method.name = const_cast<char*>(MethodName);
    method.signature = const_cast<char*>(MethodSignature);
    method.fnPtr = func_ptr;
    this->RegisterNativeMethods(&method, 1);
}

void Jvm::RegisterNativeMethod(jobject ClassLoader, const char* MethodName, const char* MethodSignature, void* func_ptr)
{
    JNINativeMethod method;
    method.name = const_cast<char*>(MethodName);
    method.signature = const_cast<char*>(MethodSignature);
    method.fnPtr = func_ptr;
    this->RegisterNativeMethods(ClassLoader, &method, 1);
}

void Jvm::RegisterNativeMethods(JNINativeMethod* Methods, std::uint32_t MethodCount)
{
    this->InitClassLoader();
    this->RegisterNativeMethods(this->systemClassLoader, Methods, MethodCount);
}

void Jvm::RegisterNativeMethods(jobject ClassLoader, JNINativeMethod* Methods, std::uint32_t MethodCount)
{
    if (ClassLoader)
    {
        env->RegisterNatives(static_cast<jclass>(ClassLoader), Methods, MethodCount);
    }
}

然后您可以创建一个加载您的 jar 的实例。

int main()
{
    Jvm VM("C:/Users/Brandon/IdeaProjects/Eos/out/production/Eos/Bot.jar");

    jclass jMain = VM.GetENV()->FindClass("eos/Main");

    if (jMain != nullptr)
    {
        jmethodID mainMethod = env->GetStaticMethodID(jMain, "main", "([Ljava/lang/String;)V");
        jclass StringClass = env->FindClass("java/lang/String");
        jobjectArray Args = env->NewObjectArray(0, StringClass, 0);
        env->CallStaticVoidMethod(jMain, MainMethod, Args);
    }
}

现在这只是展示如何使用 Main 方法运行 jar。但是,您可以从 jar 中访问任何类,并使用所需的多个参数来调用它。它不需要主线。

现在要做到这一点还有很多工作要做,但我不会教训你。问题是这是否可能,答案是肯定的.. 是的。只要你创建一个“JVM”的实例。之后,就需要通过“Package/Class”而不是“Package.Class”(如 Java 中那样)访问该类。然后调用您想要的任何方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以制作一个调用 jdbc 的 Java JNI? 的相关文章

随机推荐

  • 使用请求登录有问题的站点

    我正在尝试使用 requests 模块在 python 中创建一个脚本来登录到此site 我正在使用我的凭据 但我找不到任何方法来这样做 因为我看不到与请求一起发送所需的参数 在 Chrome 开发工具中 username SIMMTH i
  • 如何使用Maven PDF插件从Surefire Report生成PDF?

    运行 JUnit 测试后 我使用 Maven Surefire Report 插件 http maven apache org plugins maven surefire report plugin 生成 HTML 测试报告 这会产生以下
  • Kubernetes 中的 TCP 入口支持

    似乎 TCP 和 UDP 支持将在下一版本的 ingress nginx 控制器中被弃用 还有其他入口控制器支持 TCP 和 UDP 吗 或任何其他在 kubernetes 之外公开非 http 端口的解决方案 kubernetes 初学者
  • 如何在 Excel 工作表中查找精确值

    如何在 Excel 工作表中找到字符串值 我在尝试objRange Find 但这也给了我错误的地址 例如 我想要 Object paint 的地址 但它也给出 Object paint and stk 的地址 我应该如何获得精确的值 Se
  • Spring boot war文件部署在Tomcat上

    我使用 Spring Boot 1 2 4 RELEASEGS 休息服务源文件 我有 127 0 0 1 18 Jun 2015 09 59 25 0300 GET gs rest service 0 1 0 HTTP 1 1 404 10
  • Mac OS X:_tkinter.TclError:没有显示名称,也没有 $DISPLAY 环境变量

    正如我所说 我已经从 Macports 安装了 Python 3 3 现在 当我重点搜索 空闲 时 Idle Python 3 3 出现 但是 当我尝试单击它时 什么也没有发生 没有显示任何错误或任何东西 它显然不会启动 您认为可能有什么问
  • 为什么要在数据库中创建视图?

    何时以及为何有人决定需要在数据库中创建视图 为什么不直接运行一个普通的存储过程或选择呢 视图提供了多种好处 1 视图可以隐藏复杂性 如果您的查询需要连接多个表 或者具有复杂的逻辑或计算 则可以将所有逻辑编码到视图中 然后像选择表一样从视图中
  • 移动当前可执行文件c#

    我想将当前正在执行的程序集移动到 C 驱动器 当我尝试以下代码时 File Move Assembly GetEntryAssembly Location c 它给了我一个错误 mscorlib dll 中发生 System Unautho
  • Java线程安全数据库连接

    我正在编写一个 servlet 它通过访问和修改数据库中的某些表来处理每个请求 我希望与数据库的连接是线程安全的 我不想为此使用现有的库 框架 spring hibernate 等 我知道我可以通过以下方式使用 java 的 ThreadL
  • 与 multiprocessing.Pool 共享计数器

    我想用multiprocessing Value multiprocessing Lock在不同的进程之间共享一个计数器 例如 import itertools as it import multiprocessing def func x
  • .NET MAUI绑定ListView的ItemSelected事件到ViewModel

    我正在尝试将 ListView 的 ItemSelected 绑定到视图模型 但遇到了一些问题 由于我自己对其工作原理的误解 我有观点
  • Python 和 Ctypes:将结构体作为指针传递给函数以获取数据

    我已经查看了其他答案 但似乎无法使其发挥作用 我正在尝试调用 DLL 中的函数来与 SMBus 设备进行通信 该函数接受一个指向结构的指针 该结构有一个数组作为其字段之一 所以 In C typedef struct SMB REQUEST
  • 托管 Bean 内的回滚事务

    我想不在 EJB 内回滚事务 而是在 JSF 托管 bean 内回滚事务 在EJB内部我们可以使用SessionContext setRollBackOnly 但我可以在托管 bean 中使用什么 Stateless Local Accou
  • List和ArrayList这句话是什么意思?

    我正在阅读 Drools Planner 示例 并且经常遇到这样的代码 List
  • 包含彼此了解的字段的结构

    我有一组需要相互了解才能合作的对象 这些对象存储在容器中 我试图对如何用 Rust 构建我的代码有一个非常简单的想法 让我们打个比方 AComputer包含 1 Mmu 1 Ram 1 Processor In Rust struct Co
  • 使用hadoop流解压文件

    我在 HDFS 中有很多文件 所有这些文件都是一个 zip 文件 其中包含一个 CSV 文件 我正在尝试解压缩这些文件 以便可以对它们运行流作业 I tried hadoop jar usr lib hadoop mapreduce had
  • Azure 发布管道,失败阶段后继续

    我有以下天蓝色发布管道 问题是 有时我需要离开左阶段才能失败 但同时 即使失败 右阶段仍然应该执行 这可能吗 我发现的唯一的事情是 即使所选阶段部分成功也会触发 但如果前一阶段失败 它就不起作用 有时我需要离开左阶段才能失败 但同时 即使失
  • 下载html源android?

    我正在尝试下载网站源代码并将其显示在文本框中 但我似乎收到错误并且无法弄清楚 s public void getHtml throws ClientProtocolException IOException HttpClient httpC
  • 单击开始按钮时的 JavaScript 倒计时器,显示小时、分钟和秒

    我想在单击按钮时创建小时 分钟和秒的倒计时器 这是我到目前为止的代码 HTMLcode div class colomn style margin right 20px div
  • 是否可以制作一个调用 jdbc 的 Java JNI?

    我是 jni 的新手 并且非常困惑是否可以使用 jni 来实现我需要完成的任务 我想制作一个java api 它将使用jdbc来更新数据库 但是这个特定的api将从C 程序中调用 所以我想我可能应该编写通过 jdbc 访问数据库的 jni