2012-02-16 7 views
0

すべての必要なパラメータでJNIEnv-> DefineClassメソッドをバイパスしようとしていますが、常にjava.lang.NoClassDefFoundError:lsを返します。 Hello(間違った名前:ls/Hello)javaからメソッドを呼び出そうとするとエラーが発生します。何が間違っているのか分かりません。下記のJNIコードを参照してください :jni定義クラスメソッド例外メッセージ:ls.Hello(間違った名前:ls/Hello)

#include<jni.h> 
#include<ls_TestClassLoader.h> 
#include<iostream> 

using namespace std; 
//JNIEnv *, jobject, jstring, jbyteArray, jint 
JNIEXPORT jclass JNICALL Java_ls_TestClassLoader_defineClassX(JNIEnv *env, jobject obj, jstring name, jbyteArray data, jint len){ 
    JNIEnv &e=*env; 
    jboolean isCopy; 
    jclass cls= e.DefineClass(e.GetStringUTFChars(name,&isCopy),obj,e.GetByteArrayElements(data,&isCopy),500); 
    return cls; 
} 

ここでネイティブ

を呼び出すTestClassLoaderコードはまた、バイナリクラスファイルが

public class TestClassLoader extends ClassLoader { 

    static { 
     System.loadLibrary("TestClassLoader"); 
    } 
    private native Class defineClassX(String name, byte[] b, int len); 
    public TestClassLoader() { 
     super(TestClassLoader.class.getClassLoader()); 
    } 
    @Override 
    public Class<?> findClass(String className) { 
     byte classByte[]; 
     Class result = null; 
     result = (Class) classes.get(className); 
     if (result != null) { 
      return result; 
     } 
     try { 
      return findSystemClass(className); 
     } catch (Exception e) { 
     } 
     try { 
      classByte = loadData(className); 
      result = defineClassX(className, classByte, classByte.length); 
      classes.put(className, result); 

      return result; 
     } catch (Exception e) { 
      Logger.getLogger(TestClassLoader.class.getName()).log(Level.SEVERE, null, e); 
      return null; 
     } 
    } 

    private byte[] loadData(String name) { 
     try { 
      String res = "/"+name.replace(".", "/") + ".txt"; 
      InputStream is = TestClassLoader.class.getResourceAsStream(res); 
      ByteArrayOutputStream os = new ByteArrayOutputStream(); 
      int d = 0; 
      while ((d = is.read()) != -1) { 
       os.write(d); 
      } 
      return os.toByteArray(); 
     } catch (IOException ex) { 
      Logger.getLogger(TestClassLoader.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return null; 
    } 
    private Hashtable classes = new Hashtable(); 
} 

txtファイルの内容をですどんな助けでも大歓迎です。

おかげ

答えて

1

DefineClassための最後のパラメータは、配列の長さですが、一定の値を指定しました。 JNIのドキュメントには、DefineClassNoClassDefFoundErrorをスローすると書かれていませんが、このbugreportを見てください。

ClassLoader.defineClass(String name, byte[] b, int off, int len) throws NoClassDefFoundError if name does not match the name derived from the class data array.

多分あなたが指定したクラスの名前に間違っています。どのクラス名を渡すかは不明です。パッケージ名のセパレータとして機能するのは何ですか? ""または "/"?

UPD。

あなたのコードを試しました。

result = defineClassX(className, classByte, classByte.length); 

classNameあなたは合格が"ls.Hello"次のとおりです。問題は、(Javaコード)下の行です。しかし、JNIは、すべてのクラス名が "aaa/bbb/ccc/ClassName"であり、 "aaa.bbb.ccc.ClassName"ではないことを要求しています。 ./に置き換えると、クラスが読み込まれます。

はまた、あなたがGetStringUTFCharsGetByteArrayElementsを呼び出しますが、ReleaseStringUTFCharsReleaseByteArrayElementsでそれらのバランスをとるないことに注意してください。メモリリークや予期しない動作につながる可能性があります。

+0

私のoringinalで私は配列の長さとしてlenを渡しました、そして、ここで私はメソッドを呼び出す方法です。 ls.Helloは実際のパブリッククラスMain { public static void main(String [] args)ClassNotFoundException、InstantiationException、IllegalAccessExceptionをスローします。{ TestClassLoader tl = new TestClassLoader();HelloI hi =(HelloI)tl.loadClass( "ls.Hello")。newInstance(); System.out.println(hi.sayHello()); } } –

+0

問題が見つかりました。私の編集を参照してください。 – Mersenne

+0

素晴らしい!!!!!!!!!!!!!!!!。ありがとう、それは多く働いた。 –

関連する問題