В рамках одного из моих проектов мне нужно прочитать графический объект VTextField с запущенным приложением оракуловых форм и установить в нем новое значение, я могу добавить свою DLL в приложение и могу прикрепить через текущий поток, приведенный ниже, мой код для этого
JNIEnv* env;
JavaVM *jvm = NULL;
jsize jvm_count = 0;
jint res = 0;
#ifdef __STATIC_LIB_JVM
res = JNI_GetCreatedJavaVMs(&jvm, 1, &jvm_count);
#else
{
HINSTANCE hLibJVM;
typedef jint(JNICALL GetCreatedJavaVMs_t)(JavaVM**, jsize, jsize*);
GetCreatedJavaVMs_t *MyGetCreatedJavaVMs;
hLibJVM = LoadLibrary(L"jvm.dll");
MyGetCreatedJavaVMs = (GetCreatedJavaVMs_t*)GetProcAddress(hLibJVM, "JNI_GetCreatedJavaVMs");
res = MyGetCreatedJavaVMs(&jvm, 1, &jvm_count);
}
#endif
if (res == 0)
{
if (jvm_count == 0)
{
jvm = NULL;
}
}
else jvm = NULL;
bool mustDetach = false;
//jint retval = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
jint retval = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if (retval == JNI_EDETACHED)
{
JavaVMAttachArgs args;
args.version = JNI_VERSION_1_6;
args.name = NULL;
args.group = NULL;
retval = jvm->AttachCurrentThread((void**)&env, &args);
mustDetach = true; // to clean up afterwards
}
else{
fprintf(JNIStatus, "JNI is not processing\n"); // should never happen
}
if (retval != JNI_OK){
fprintf(JNIStatus, "JNI is not ok\n"); // should never happen
}
else{
fprintf(JNIStatus, "JNI is ok\n"); // should never happen
}
if (retval>=0)
fprintf(JNIStatus, "Attachcurrentthread was successfull\n");
здесь я получаю вывод, так как присоединить текущий поток был успешным, но после этого, когда я пытаюсь найти класс, используя приведенный ниже код, система не может найти класс для этого
char* strin;
strin = "abcdef";
jstring str = env->NewStringUTF(strin);
jfieldID fid;
jclass clazz = env->FindClass("oracle/forms/ui/VTextField");
if (clazz == NULL) {
fprintf(JNIStatus, "Can't find class %s", clazz);
}
Даже я думал об этом из-за локальной ссылки, но я пытался сделать объект jclass также глобальной ссылкой, но не повезло 🙁
/* Create a global reference */
jclass clazzLUSCore = (_jclass*)env->NewGlobalRef(clazz);
/* The local reference is no longer useful */
env->DeleteLocalRef(clazz);
/* Is the global reference created successfully? */
if (clazzLUSCore == NULL) {
fprintf(JNIStatus, "Error - clazzLUSCore is still null when it is suppose to be global\n");
}
Я новичок в C ++, пожалуйста, помогите мне в этом, я не могу найти работающий класс приложения, мне нужно достичь этого без доступа к коду сервера.
Согласно комментарию @michael, я пытался добавить это, но я думаю, что это исключение. поэтому не может получить имя класса
JavaVM* gJvm = nullptr;
static jobject gClassLoader;
static jmethodID gFindClassMethod;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
gJvm = pjvm; // cache the JavaVM pointer
auto env = getEnv();
//replace with one of your classes in the line below
auto randomClass = env->FindClass("oracle/forms/ui/VTextField");
jclass classClass = env->GetObjectClass(randomClass);
auto classLoaderClass = env->FindClass("java/lang/ClassLoader");
auto getClassLoaderMethod = env->GetMethodID(classClass, "getClassLoader",
"()Ljava/lang/ClassLoader;");
gClassLoader = env->CallObjectMethod(randomClass, getClassLoaderMethod);
gFindClassMethod = env->GetMethodID(classLoaderClass, "findClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
return JNI_VERSION_1_6;
}
jclass findClass(const char* name) {
return static_cast<jclass>(getEnv()->CallObjectMethod(gClassLoader, gFindClassMethod, getEnv()->NewStringUTF(name)));
}
JNIEnv* getEnv() {
JNIEnv *env;
int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6);
if (status < 0) {
status = gJvm->AttachCurrentThread((void**)&env, NULL);
if (status < 0) {
return nullptr;
}
}
return env;
}
Вы должны получить правильный загрузчик классов.
HWND
для главного окна приложения. Вы можете использовать инструмент Spy ++, чтобы получить точные свойства этого окна.jawt.dll
, используя Win32 LoadLibrary API. Эта DLL обычно находится в родительском каталоге каталога, содержащего jvm.dll
, Пример:C:\Program Files (x86)\Java\jre1.8.0_73\bin\jawt.dll C:\Program Files (x86)\Java\jre1.8.0_73\bin\client\jvm.dll
У вас есть много способов получить LoadLibrary
призыв к успеху:
"jawt.dll"
jvm.dll
, с помощью GetModuleFileName и построить новый путь с ним.java.exe
) передача дескриптора модуля NULL GetModuleFileName
, Вы должны получить bin
дорожка.После того, как вы успешно загрузили jawt.dll
использовать GetProcAdress чтобы получить _JAWT_GetAWT@8
функция, и вызовите это. Exemple:
// error checking committed (for clarity...)
typedef jboolean (JNICALL * PGETAWT)(JNIEnv* env, JAWT* awt);
PGETAWT pGetAWT = (PGETAWT)GetProcAddress( hModJAWT, "_JAWT_GetAWT@8" );
JAWT jawt;
jawt.version = JAWT_VERSION_1_4;
pGetAWT( env, &jawt );
Теперь вы можете назвать замечательный GetComponent
API:
jobject jObjMainWindow = jawt->GetComponent( env, (void*)hWndOfTheMainOracleWindow );
Затем используйте JNI для получения jclass
этого главного окна, а затем вызвать getClassLoader
метод класса Class.
С тот Class Loader, FindClass
должно работать намного лучше.
Других решений пока нет …