Ich möchte eine Methode aus Performancegründen nativ auslagern. Das ist mir auch schon erfolgreich gelungen. Da hab ich allerdings keine packages und statischen Methoden verwendet.
Mein Code:
MUtilities (package: utils)
listing.cpp
MUtilities.h (generiert durch javah -jni utils.MUtilities)
Das Programm lässt sich erfolgreich übersetzen mit
Jetzt liegt die Library 'counter.dll' im Verzeichnis 'native' in meinem Hauptprogrammordner.
Beim Programmstart wird die DLL auch erfolgreich geladen, doch beim Aufruf der nativen Methode kommt ein UnsatisfiedLinkError:
Wo kann da das Problem liegen?
Mein Code:
MUtilities (package: utils)
Code:
package utils;
import [...]
public class MUtilities {
// CONSTANTS
public static final int OVERWRITE_FILES = 0;
public static final int UNCHANGE_EXISTING_FILES = 1;
public static native int countFilesInDirectory( String dir );
private static boolean loadLib = true;
static {
try {
String lib = new File(".").getAbsolutePath() +
File.separatorChar +
"native" +
File.separatorChar +
"counter." +
((System.getProperty("os.name").equals("Linux")) ? "so" : "dll");
System.load( lib );
System.out.println( lib );
} catch ( java.lang.UnsatisfiedLinkError err ) {
loadLib = false;
System.err.println( "Kann Library nicht laden!" );
}
}
[...]
}
listing.cpp
Code:
#include <iostream>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <jni.h>
#include "MUtilities.h"
int count_files( const char* path ) {
DIR* dir;
struct dirent* dirpointer;
if ( (dir=opendir(path)) == NULL ) {
std::cerr << "Verzeichnis konnte nicht geoeffnet werden!" << std::endl;
return 0;
}
int i=0;
char* tmp_file = new char[500];
struct stat* file_info;
while ( (dirpointer=readdir(dir)) != NULL ) {
if ( strcmp(dirpointer->d_name, ".") && strcmp(dirpointer->d_name, "..") ) {
strncpy( tmp_file, path, 450 );
strncat( tmp_file, "/", 1 );
strncat( tmp_file, dirpointer->d_name, 49 );
file_info = new struct stat;
if ( stat(tmp_file, file_info) != -1 && file_info->st_mode & S_IFDIR ) {
i += count_files( tmp_file );
//printf( "%s\n", tmp_file );
} else {
i++;
}
delete file_info;
}
}
closedir( dir );
return i;
}
JNIEXPORT jint JNICALL Java_utils_MUtilities_countFilesInDirectory( JNIEnv* env, jclass obj, jstring str ) {
return count_files( env->GetStringUTFChars(str, NULL) );
}
MUtilities.h (generiert durch javah -jni utils.MUtilities)
Code:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class utils_MUtilities */
#ifndef _Included_utils_MUtilities
#define _Included_utils_MUtilities
#ifdef __cplusplus
extern "C" {
#endif
#undef utils_MUtilities_OVERWRITE_FILES
#define utils_MUtilities_OVERWRITE_FILES 0L
#undef utils_MUtilities_UNCHANGE_EXISTING_FILES
#define utils_MUtilities_UNCHANGE_EXISTING_FILES 1L
/*
* Class: utils_MUtilities
* Method: countFilesInDirectory
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_utils_MUtilities_countFilesInDirectory
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
Das Programm lässt sich erfolgreich übersetzen mit
Code:
mingw32-g++ -I C:\Programme\Java\jdk1.6.0\include -shared -o counter.dll listing.cpp
Jetzt liegt die Library 'counter.dll' im Verzeichnis 'native' in meinem Hauptprogrammordner.
Beim Programmstart wird die DLL auch erfolgreich geladen, doch beim Aufruf der nativen Methode kommt ein UnsatisfiedLinkError:
Exception in thread "main" java.lang.UnsatisfiedLinkError: utils.MUtilities.countFilesInDirectory(Ljava/lang/StringI
at utils.MUtilities.countFilesInDirectory(Native Method)
at main.Starter.main(Starter.java:66)
Wo kann da das Problem liegen?