以下代码有一个意外的行为:File参数在运行时变为DirectoryListingPerfTest。
我认为java堆已损坏且我的本机代码没有使用正确的参数调用它。
这是Java代码:
static jclass File;
static jmethodID FileCtor;
static void Java_fs_DirectoryListingPerfTest_find_r(
JNIEnv * env,
const char * path,
jobject listener,
jmethodID accept )
{
jstring jPath = env->NewStringUTF( path );
jobject file = env->NewObject( File, FileCtor, jPath );
jobject gFile = env->NewGlobalRef( file );
env->CallBooleanMethod( listener, accept, gFile );
DIR * dir = opendir( path );
if( dir ) {
struct dirent * entry;
while(( entry = readdir( dir )) != NULL ) {
if( ( 0 == strcmp( entry->d_name, "." ))
||( 0 == strcmp( entry->d_name, ".." )))
{
continue;
}
if( entry->d_type == DT_DIR ) {
char * buffer = (char *)malloc(
strlen( path ) + 1 + strlen( entry->d_name ) + 1 );
strcpy( buffer, path );
strcat( buffer, "/" );
strcat( buffer, entry->d_name );
Java_fs_DirectoryListingPerfTest_find_r(
env, buffer, listener, accept );
free( buffer );
}
}
closedir( dir );
}
}
JNIEXPORT void JNICALL Java_fs_DirectoryListingPerfTest_find(
JNIEnv * env,
jclass clazz,
jstring jpath,
jobject listener )
{
if( File == NULL ) {
File = env->FindClass( "java/io/File" );
FileCtor = env->GetMethodID( File, "<init>", "(Ljava/lang/String;)V");
}
jclass FileFilter = env->GetObjectClass( listener );
jmethodID accept =
env->GetMethodID( FileFilter, "accept", "(Ljava/io/File;)Z");
const char * path = env->GetStringUTFChars( jpath, JNI_FALSE );
Java_fs_DirectoryListingPerfTest_find_r( env, path, listener, accept );
env->ReleaseStringUTFChars( jpath, path );
}
这是C ++ JNI代码:
native(1): 584,76 ms
class fs.DirectoryListingPerfTest
class fs.DirectoryListingPerfTest
... (a lot !)
class fs.DirectoryListingPerfTest
Exception in thread "main" java.lang.ClassCastException: fs.DirectoryListingPerfTest cannot be cast to java.lang.Comparable
at java.util.TreeMap.put(TreeMap.java:565)
at java.util.TreeSet.add(TreeSet.java:255)
at fs.DirectoryListingPerfTest.accept(DirectoryListingPerfTest.java:16)
at fs.DirectoryListingPerfTest.find(Native Method)
at fs.DirectoryListingPerfTest.main(DirectoryListingPerfTest.java:91)
这是执行追踪:
<html>
<script language="javascript">
function encrypt() {
var texttoencrypt = document.getElementById("text").innerHTML;
var encrypted = btoa(texttoencrypt)
document.getElementById("text").innerHTML = encrypted;
}
</script>
<head></head>
<title>Base64 Encrypt</title>
<body>
<textarea id="text" rows="4" cols="50" autofocus placeholder="Put text here."></textarea>
<br>
<button onclick="encrypt()">Encrypt</button>
<button onclick="decrypt()">Decrypt</button>
</body>
</html>
答案 0 :(得分:1)
您无法在调用之间缓存Java对象。这段代码错了:
static jclass File;
static jmethodID FileCtor;
...
if( File == NULL ) {
File = env->FindClass( "java/io/File" );
FileCtor = env->GetMethodID( File, "<init>", "(Ljava/lang/String;)V");
}
如果要缓存Java值,通常需要创建全局引用。参见:
答案 1 :(得分:0)
感谢Andrew,从您的建议中,我已经让ant测试了一个更正的C ++版本,希望这会有所帮助:
namespace fs {
class DirectoryListingPerfTest {
private:
JNIEnv * _env;
jclass _File;
jmethodID _FileCtor;
jobject _listener;
jmethodID _accept;
public:
DirectoryListingPerfTest(
JNIEnv * env,
jclass File,
jmethodID FileCtor,
jobject listener,
jmethodID accept )
:
_env ( env ),
_File ( File ),
_FileCtor( FileCtor ),
_listener( listener ),
_accept ( accept )
{}
void find( const char * path ) {
jstring jPath = _env->NewStringUTF( path );
jobject file = _env->NewObject( _File, _FileCtor, jPath );
jobject gFile = _env->NewGlobalRef( file );
_env->CallBooleanMethod( _listener, _accept, gFile );
DIR * dir = opendir( path );
if( dir ) {
struct dirent * entry;
while(( entry = readdir( dir )) != NULL ) {
if( ( 0 == strcmp( entry->d_name, "." ))
||( 0 == strcmp( entry->d_name, ".." )))
{
continue;
}
if( entry->d_type == DT_DIR ) {
char * buffer = (char *)malloc(
strlen( path ) + 1 + strlen( entry->d_name ) + 1 );
strcpy( buffer, path );
strcat( buffer, "/" );
strcat( buffer, entry->d_name );
find( buffer );
free( buffer );
}
}
closedir( dir );
}
}
private:
DirectoryListingPerfTest( const DirectoryListingPerfTest & );
DirectoryListingPerfTest & operator = ( const DirectoryListingPerfTest & );
};
}
JNIEXPORT void JNICALL Java_fs_DirectoryListingPerfTest_find(
JNIEnv * env,
jclass clazz,
jstring jpath,
jobject listener )
{
jclass File = env->FindClass( "java/io/File" );
jmethodID FileCtor = env->GetMethodID( File, "<init>", "(Ljava/lang/String;)V");
jclass FileFilter = env->GetObjectClass( listener );
jmethodID accept = env->GetMethodID( FileFilter, "accept", "(Ljava/io/File;)Z");
const char * path = env->GetStringUTFChars( jpath, JNI_FALSE );
fs::DirectoryListingPerfTest( env, File, FileCtor, listener, accept ).find( path );
env->ReleaseStringUTFChars( jpath, path );
}