2023-01-19 361
我是JNI的新手,如果可以使用JNI来实现我需要做的事情,我非常困惑.我想制作一个Java API,将使用JDBC更新数据库,但是该特定API将从C ++程序调用.
因此,我认为我可能应该编写JNI代码,该代码通过JDBC访问数据库(甚至可能吗?),创建C ++代码并生成DLL,以便其他C ++程序可以将DLL调用以更新数据库.这一切可能吗?如果是这样,我该如何在JNI中真正致电JDBC?
如果最终制作了此DLL,也可以将其称为吗?
我的另一个想法是,也许我应该制定一个常规的Java程序来更新数据库,然后使用Say IKVM将Java类包装到C ++ DLL中?
问题是我必须使用Java使用访问数据库.我们的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);
}
}
现在,这只是显示了如何使用主方法运行罐子.但是,您可以从JAR中访问任何类,并使用所需的许多参数调用.它不需要主.
现在要这样做要做更多的工作,但是我不会讲您.问题是是否可能是可能的,答案是肯定的.只要您创建一个” JVM”的实例.之后,这是通过java中完成的”软件包/类”而不是” package.class”访问课程的问题.然后调用您想要的任何方法.
以上所述是小编给大家介绍的有没有可能做一个调用jdbc的Java JNI?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/25875.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态