当前位置: 首页 > 面试题库 >

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

莫逸仙
2023-03-14
问题内容

我是jni的新手,如果可以使用jni实现需要完成的工作,我会感到非常困惑。我想制作一个Java api,它将使用jdbc更新数据库,但是将从C
++程序调用此特定api。

因此,我认为我可能应该编写通过jdbc访问数据库的jni代码(甚至可能吗?),创建C 代码并生成dll,以便其他C

程序可以调用dll来更新数据库。这一切可能吗?如果是这样,我如何在jni中真正调用jdbc?如果最终生成了该dll,Fortran也可以调用它吗?

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

问题是我必须使用Java使用Access数据库。我们的C ++程序根本不会访问数据库,最好是可以通过系统调用来访问此Java api。

还是有更好的方法呢?

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

非常感谢!!

更新: 问题不是所有计算机都安装了C postgresql驱动程序,但它们确实安装了Java
postgresql驱动程序。我们不想强迫所有人安装C
db驱动程序,并且不会对这些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 Method运行jar。但是,您可以从jar中访问ANY类,并使用所需的许多参数来调用它。它不需要主电源。

现在要做很多工作,但是我不会教你。问题是是否可能,答案是肯定的。只要您创建“ JVM”的实例。之后,只需通过Java中的“ Package /
Class”(而不是“ Package.Class”)访问类,然后调用所需的任何方法即可。



 类似资料:
  • 问题内容: 我希望在Web应用程序中以树状结构显示数据。我希望将Angular用于此任务。 看起来ng-repeat可以让我遍历节点列表,但是当给定节点的深度增加时,该如何嵌套呢? 我尝试了以下代码,但是HTML的自动转义阻止了此操作。另外,结束ul标签放在错误的位置。 我很确定我将完全以错误的方式解决这个问题。 有任何想法吗? 问题答案: 看看这个小提琴 原文:http: //jsfiddle.

  • 帮助我正试图用plotly绘制甘特图,但我没有找到一种方法。甘特图类似于水平条形图,每个条形图都有一个“起点”坐标。所以它看起来像: 我找不到让条形图中的“条形图”从特定的X坐标开始的方法。有什么提示/技巧/提示吗?

  • 问题内容: 我喜欢旧的Java小程序。但是因为我真的很喜欢JFX的工作方式,所以我想使用JFX编写一些游戏(甚至是游戏制作系统,谁知道?),但是我希望能够将它们发布到我的网站上。人们将如何去做呢? 问题答案: 是的,您应该可以将JavaFX嵌入到您的网页中: http://docs.oracle.com/javase/8/docs/technotes/guides/deploy/deploymen

  • 问题内容: 我想知道是否有一种方法可以对数据库进行异步调用吗? 例如,假设我有一个很大的请求,需要很长时间来处理,我想发送请求并在请求将返回值时(通过传递侦听器/回调等)接收通知。我不想阻塞等待数据库答复。 我不认为使用线程池是一种解决方案,因为它无法扩展,在大量并发请求的情况下,这会产生大量线程。 我们正在面对网络服务器的此类问题,并且我们已经找到解决方案,方法是使用select / poll

  • 问题内容: 是否可以从Java调用COM API(特别是HP / Mercury Quality Center OTA API)?如果是这样,最好的方法是什么? 像JACOB一样合适吗? 代码片段对于基础知识会有所帮助:-) 问题答案: jacob:是的,http://sourceforge.net/projects/jacob- project/ 是一个活跃的项目,可以很好地满足您的目的。 您可

  • 我目前正在开发一个嵌入JCEF用于前端交互的IDEA扩展。一旦用户单击按钮,将执行中实现的方法,并执行一项耗时的任务。 这个耗时的任务是在一个方法中实现的(在主线程以外的线程上异步执行,以防UI被冻结),并以如下形式包装