2011-11-16 101 views
1

我正在处理在Playframework中使用kyotocabinet。 并发生以下错误。如何在playframework中使用kyotocabinet(JNI)?

我使用Eclipse和playframework-1.2.3。 和kyotocabinet是本地库,所以我使用它的Java绑定。

重现代码很简单。 在控制器:

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) 我将kyotocabinet.dll的位置配置为我的playframework项目的Java Build Path> Source> Native Library位置。 ,在其他项目中效果很好。

如何在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 

回答

1

我假设你只需要如果将DDL您的项目通过System.load

加载DLL为Java,您可以通过Play.getFile加载在您的@OnApplicationStart控制器中。这应该会在JVM处于活动状态时让您的应用程序可用。

编辑:

@KenichiYamamoto Play.getFile从应用程序路径获取文件。你正试图在那里使用完整的路径。

Read this关于将文件加载到容器中。这可能是(由于Play编译 - 重载系统),你正在触及“已经加载”的错误。尝试通过添加系统来遵循示例。在你的@OnApplicationStart中加载一个静态块

+0

感谢您的建议。我添加了结果。 – KenichiYamamoto

+0

@KenichiYamamoto请参阅更新 –

0

按照pere的说法,但使用应用程序根目录中的相对路径。不是绝对路径。即Play.getFile(“lib \ myfile.dll”)