JNI class java non trouvées à partie du C++

oimy

Membre confirmé
29 Mai 2018
14
0
41
Bonjour,

Je travail sur macOS 10.13.3 avec JDK 1.8.0.172

J'ai un programme en C++ qui créé une JVM pour appeler un programme JAVA.
Mon problème est que la JVM et l'environnement JNI sont corrects, j'arrive à récupérer la version de java utilisé, mais lorsque je veux récupérer la class JAVA (avec FindClass()) que j'ai créée, je récupère un pointeur NULL. Mes variables d'environnement $PATH et $CLASSPATH sont initialisées sur usr/bin:usr/local/bin:usr/sbin:/users/.../repertoire_avec_ma_class

Voici mon make :
Bloc de code:
g++ -o main -I /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include/ -I /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/include/darwin/ -L /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/server/ -L /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/jli/  main.cpp -ljli -ljvm -lobjc


Voici mon JAVA :
Bloc de code:
public class MyTest2 {
    
     public static void main(String[] args) {
         System.out.println("Hello, World in java from mymain");
       
     }
}

Voici mon C++

Bloc de code:
// Example 2 of JNI invocation. 
// The java environment is prepared.  Errors are reported.
// Call to a simple static java methods
// License: ZLIB license (see license.txt)
// (c) Copyright 2015 by cth027

#include <iostream>
#include <jni.h>
#include <objc/objc-runtime.h>

void runCocoaMain(void)
{
    id clazz = (id) objc_getClass("NSApplication");
    id _Nullable app = objc_msgSend(clazz, sel_registerName("sharedApplication"));
   
    objc_msgSend(app, sel_registerName("run"));
}

int main()
{
    using namespace std;
   
   
    JavaVM *jvm;       /* denotes a Java VM */
    JNIEnv *env;       /* pointer to native method interface */
    JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
    JavaVMOption* options = new JavaVMOption[1];
    options[0].optionString = (char*) "-Djava.class.path=.";
    options[1].optionString = (char*) "-verbose: gc,class,jni";
    vm_args.version = JNI_VERSION_1_6;
    vm_args.nOptions = 2;
    vm_args.options = options;
   
    //cout << "options2" << vm_args.options[0] << endl;
    vm_args.ignoreUnrecognized = JNI_TRUE;
    /* load and initialize a Java VM, return a JNI interface pointer in env */
    jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  // YES !!
    delete options;    // we then no longer need the initialisation options.

    //========================= analyse errors if any  ==============================
    // if process interuped before error is returned, it's because jvm.dll can't be
    // found, i.e.  its directory is not in the PATH.
if (rc == JNI_ERR) {
    printf("All done, bye bye!\n");
}
    if(rc != JNI_OK) {
        if(rc == JNI_EVERSION)
            cerr << "FATAL ERROR: JVM is oudated and doesn't meet requirements" << endl;
        else if(rc == JNI_ENOMEM)
            cerr << "FATAL ERROR: not enough memory for JVM" << endl;
        else if(rc == JNI_EINVAL)
            cerr << "FATAL ERROR: invalid ragument for launching JVM" << endl;
        else if(rc == JNI_EEXIST)
            cerr << "FATAL ERROR: the process can only launch one JVM an not more" << endl;
        else
            cerr << "FATAL ERROR:  could not create the JVM instance (error code " << rc << ")" << endl;
        cin.get();
        exit(EXIT_FAILURE);
    }
   
    cout << "JVM load succeeded. \nVersion ";
    jint ver = env->GetVersion();
    cout << ((ver >> 16) & 0x0f) << "." << (ver & 0x0f) << endl;
   

    cout << "OK jusqu'ici " << endl;
    // First call to JAVA ==================================================================
    jclass cls2 = env->FindClass("MyTest2");  // try to find the class
    cout << " -> " << env->FindClass("MyTest2") << endl;
    if(cls2 == nullptr) {
        cerr << "ERROR: class not found !" << endl;
    }
    else {                                  // if class found, continue
        cout << "Class MyTest found" << endl;
               
        jmethodID mid = env->GetStaticMethodID(cls2, "run", "()V");  // find method
        if(mid == nullptr)
            cerr << "ERROR: method void mymain() not found !" << endl;
        else {
            cout << "===Call to java==================" << endl;
           
            env->CallStaticVoidMethod(cls2, mid);                      // call method
            //runCocoaMain();
            cout << "===End of call to java==========="<<endl;
        }
    }
    // End JAVA calls ==================================================================


    jvm->DestroyJavaVM();

    cout << "Press any key...";
    cin.get();
}

mon soucis est que quand j'utilise la fonction
Bloc de code:
jclass cls2 = env->FindClass("MyTest2");
je me retrouve avec un pointeur NULL.

Je pense que celà doit être une erreur de configuration mais je ne trouve pas où.

Merci de votre aide
 

oimy

Membre confirmé
29 Mai 2018
14
0
41
J'avais déjà essayé, j'ai le même problème.
Le soucis ne viens pas de -Djava.class.path mais d'une config externe au programme je pense, car ce code fonctionne sur d'autres machines.

Sinon m'indiquer comment faire pour vérifier la valeur du class_path dans mon programme C++ pourrais m'aider à avancer.
 

byte_order

Membre actif
31 Juillet 2012
305
63
LD_LIBRARY_PATH pointe bien sur le répertoire /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/server ?

Et, euh..., la classe Java est bien compilée ?
 

oimy

Membre confirmé
29 Mai 2018
14
0
41
Bon désolé, c'était nul de ma part il fallait que je rajoute -I Mon repertoire de travail dans la compile du C++, et c'est le LYLD_LIBRARY_PATH qu'il faut initialiser.

Merci de vos réponses quand même.

mon problème c'est déplacé. La class est trouvé cool.

Mais avec ce code java :
Bloc de code:
// MyTest.java test class for JNI experimentation
// example 2
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

public class MyTest2 {
  
    public static class Starter implements Runnable {
        public void run() {
            System.out.println("Runnning on AWT Queue.");
          
            JFrame.setDefaultLookAndFeelDecorated(true);
            JFrame frame = new JFrame("That's a frame!");
            frame.setSize(400, 200);
            JLabel label = new JLabel("A Label");
            frame.getContentPane().add(label);
            frame.setLocationRelativeTo(null);
            //Termine le processus lorsqu'on clique sur la croix rouge
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //frame.pack();
            frame.setVisible(true);
          
            //JButton button;
            //JPanel panel;
          
            // my error lines are under the "panel" and  "button"
            // it says i must implement the variables. what does that mean???
            //panel.add(button);
        }
    }
  
    public static class GUI implements Runnable {
        public void run() {
            try {
                System.out.println("Going to put something on the AWT queue.");
                SwingUtilities.invokeAndWait(new Starter());
            } catch (Exception exc) {
                throw new RuntimeException(exc);
            }
        }
    }
  
    public static void run() {
        Thread gui = new Thread(new GUI());
        gui.start();
    }
}

c'est la méthode run() que le c++ ne trouve pas
 
Dernière édition:

oimy

Membre confirmé
29 Mai 2018
14
0
41
Merci beaucoup, mes paramètres dans GetStaticMethodeID() n'étaient pas bon.

Félicitation pour le forum et les personnes y participant. Depuis le temps que je participe à des forums de programmation, pour une fois les réponses sont simples, directes et pas à côté. Encore merci.

Comment marque t on le sujet résolu ?