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



## oimy (29 Mai 2018)

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 :

```
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 :

```
public class MyTest2 {
    
     public static void main(String[] args) {
         System.out.println("Hello, World in java from mymain");
       
     }
}
```

Voici mon C++


```
// 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 
	
	



```
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


----------



## byte_order (29 Mai 2018)

Essayez avec le nom FQN de la classe, mais avec / à la place des points : votre/nom/de/package/MyTest2


----------



## oimy (29 Mai 2018)

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 (29 Mai 2018)

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 (29 Mai 2018)

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 :

```
// 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


----------



## byte_order (29 Mai 2018)

Verifier les signatures des methodes ?

javap -s -p MyTest


----------



## oimy (30 Mai 2018)

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 ?


----------

