1

Playframework で kyotocabinet を使用することに取り組んでいます。となり、以下のエラーが発生しました。

私はEclipseとplayframework-1.2.3を使用しています。kyotocabinet はネイティブ ライブラリなので、その Java-Binding を使用しています。

再現コードは簡単です。コントローラーで:

public static void somePage() {
    DB db = new DB();//error occurred
    render();
}

Internal Server Error (500) for request GET /
Execution exception (In /app/controllers/TestApp.java around line 45)
NoClassDefFoundError occured : Could not initialize class kyotocabinet.DB

play.exceptions.JavaExecutionException: Could not initialize class kyotocabinet.DB
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:229)
    at Invocation.HTTP Request(Play!)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class kyotocabinet.DB
    at controllers.TestApp.somePage(TestApp.java:45)
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:546)

    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:500)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:476)

    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:471)

    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:159)
    ... 1 more

Eclipse でのビルドは完了しましたが、実行時にエラーが発生しました。

kyotocabinet.dll が見つからないためだと思います (jkyotocabinet.jar のみが見つかりました)。他のプロジェクトでも良かったです。

playframework でネイティブ ライブラリを使用するには? 例やチュートリアルはありますか?

Play.getFile と System.load が機能しませんでした。

package controllers;
import play.Play;
import play.jobs.*;

@OnApplicationStart
public class Bootstrap extends Job {
public void doJob() {
    String path = "D:/MyProject/lib/jkyotocabinet.dll";
    Play.getFile(path);
    //System.load(path); if this was enabled, following error occurred: "Native Library D:\MyProject\lib\jkyotocabinet.dll already loaded in another classloader". so I guess the dll was loaded.
    System.out.println("bootstrap loaded");//this is displayed.
}
}

UnsatisfiedLinkError occured : no jkyotocabinet in java.library.path

この日本語のブログは、Play!Framework がネイティブ ライブラリを読み込めないことを伝えています。 http://d.hatena.ne.jp/hjym_u/20110702/1309609277

私はすでにこれらを試しました:絶対パス、相対パス、System.load、System.loadLibrary、Play.getFile。

決定的なアプローチとして、jkyotocabinet.dll を現在のディレクトリ (D:/MyProejct/) に置き、このコードを記述しました。

public static void somePage(){
    File f = Play.getFile("jkyotocabinet.dll");
        if(f != null && f.isFile() && f.canRead() && f.canExecute()){//true
            DB db = new DB();//error occured. it reached here.
        }
    render();
}

Execution exception
NoClassDefFoundError occured : Could not initialize class kyotocabinet.DB

Play.getFile はパス「jkyotocabinet.dll」を見つけたので、jkyotocabinet.dll は現在のディレクトリにあるので、jvm は自動的にそれを見つけるはずです。

誰でも playframework で JNI を使用できますか?

最終的に、kyotocabinet を PROD モードとして使用できましたが、DEV モードでは使用できませんでした。

プロジェクト/conf/application.conf

#application.mode=dev
application.mode=prod
4

2 に答える 2

1

System.loadを介してdllをJavaにロードするだけでよいと思います

プロジェクトに ddl を配置すると、 @OnApplicationStart コントローラー内の Play.getFile を介してロードできます。これにより、JVM が動作している間、アプリケーションで使用できるようになります。

編集:

@KenichiYamamoto Play.getFile は、アプリケーション パスからファイルを取得します。そこでフルパスを使用しようとしています。

コンテナへのファイルのロードについては、こちらをお読みください。(Play のコンパイルとリロードのシステムが原因で) 「既にロードされています」というエラーが発生している可能性があります。@OnApplicationStart の静的ブロック内に System.load を追加して、例に従ってみてください。

于 2011-11-16T10:27:59.473 に答える
0

pere の言うとおりにしますが、アプリケーション ルートからの相対パスを使用します。絶対パスではありません。すなわち Play.getFile("lib\myfile.dll")

于 2011-11-16T12:39:30.737 に答える