Java 运行新鲜jar文件时openjdk出现致命错误
我想实现一个Java 运行新鲜jar文件时openjdk出现致命错误,java,openjdk,Java,Openjdk,我想实现一个ApplicationChangeMonitor,它监视文件系统中当前执行的jar文件中的更改。当检测到更改时,应用程序应重新启动。我正在使用一个测试来检测变化 设置: 在(Windows)Eclipse中开发samba共享上的工作区(Linux系统) jar文件由Eclipse maven(m2e)在该samba共享上生成 jar文件在Linux系统上从shell执行(使用openjdk) 因此,每次创建新的jar文件时,都应该在Linux系统上重新启动正在运行的应用程序。首先
ApplicationChangeMonitor
,它监视文件系统中当前执行的jar文件中的更改。当检测到更改时,应用程序应重新启动。我正在使用一个测试来检测变化
设置:
- 在(Windows)Eclipse中开发samba共享上的工作区(Linux系统)
- jar文件由Eclipse maven(m2e)在该samba共享上生成
- jar文件在Linux系统上从shell执行(使用openjdk)
while true ; do java -jar application.jar ; done
奇怪的是,在应用程序更改后,我仍然会出现一两次致命错误。例如:
- java-jar application.jar这是因为在将新文件写入磁盘时,您会收到新文件的通知。这对于WatchService来说是一件坏事,它会在创建新文件但尚未完全写入磁盘时通知您
当新的jar文件被写入磁盘时,jar文件被进程锁定,进程将jar文件写入磁盘。在文件创建者进程未解锁文件之前,您无法访问文件
解决方法是:您必须尝试打开文件,如果文件被打开,则文件已完全写入磁盘。若无法打开文件,请等待一段时间(或者不要等待,请尝试下一步),然后尝试下一步打开文件
要解锁文件,请实现如下操作:
public void unlockFile(String jarFileName){ FileInputStream fis = null; while(true){ try{ // try to open file fis = new FileInputStream(jarFileName); // you succeed to open file // return // file will be closed in finally block, as it will always executed return; }catch(Exception e){ // file is still locked // you may sleep for sometime to let other process finish with file and // file gets unlocked // if you dont have problem with this process utilizing CPU, dont sleep! try{ Thread.sleep(100); }catch(InterruptedException ie){ } }finally{ if(fis != null){ try{ fis.close(); }catch(Exception e){ } } } }
解决您的问题, 您告诉我:“我只是在检测到更改并用bash实现重启机制后让应用程序自行结束” 所以,在结束java过程之前,按照我在上述方法中的建议解锁文件。我相信错误会消失的。试着让我知道结果 大概是这样的:void shutDownMethod(){ // get file name from watcher, below line will depend on your logic and code. String jarFileName = watcherThread.getNewNotifiedFile(); // unlock new jar file. unlockFile(jarFileName); // shutdown JVM System.exit(0); // bash will restart JVM }
public void unlockFile(String jarFileName){ FileInputStream fis = null; while(true){ try{ // try to open file fis = new FileInputStream(jarFileName); // you succeed to open file // return // file will be closed in finally block, as it will always executed return; }catch(Exception e){ // file is still locked // you may sleep for sometime to let other process finish with file and // file gets unlocked // if you dont have problem with this process utilizing CPU, dont sleep! try{ Thread.sleep(100); }catch(InterruptedException ie){ } }finally{ if(fis != null){ try{ fis.close(); }catch(Exception e){ } } } }
void shutDownMethod(){ // get file name from watcher, below line will depend on your logic and code. String jarFileName = watcherThread.getNewNotifiedFile(); // unlock new jar file. unlockFile(jarFileName); // shutdown JVM System.exit(0); // bash will restart JVM }
我就是这么想的(见最后一段)。但是(1)在最后一次更改后500毫秒的延迟后,我缓冲更改并采取措施(因此,
不再提供任何更改事件),(2)为什么md5sum会打印相同的sum(无论它是否工作),(3)java不会给出“无效或损坏的jarfile”之类的错误,而不是致命的退出?[我实现了(1),因为进程实际上可以获取锁,但Eclipse给出了错误消息。可能这些现象是由于samba的具体情况造成的。]我真的没有得到您正在尝试的,您在哪个进程中检查校验和?您得到的校验和是正确的,因为这不是java进程!看最后一行:我在bash中计算校验和,在应用程序结束后和重新启动之前。现在,在第一次或两次尝试之后,通常会出现致命的错误,之后jar就可以正常运行了。jar的所有三次校验和都相同,都是从shell计算的,在运行jar=>之前,文件必须全部完成!如果jar没有完全写入,我会得到(WatchService
)。如果是这样的话,我有时无法实例化SLF4J LoggerFactory(错误:无效或损坏的jarfile
),有时会丢失不同的类,有时会出现致命错误(java.lang.NoClassDefFoundError:ch/qos/logback/core/joran/spi/JoranException
)。等待几秒钟后,我可以毫无问题地运行应用程序。您是否按照我的回答尝试在解锁文件后退出Java?并从bash循环中删除检查校验和,然后按照我的回答进行尝试。对于您的问题:“首先,我尝试使应用程序自行重新启动”您是如何重新启动java进程本身的?如果您使用其他java进程来重新启动此java进程,我将为您提供另一个解决方案!java运行时环境检测到致命错误:
void shutDownMethod(){ // get file name from watcher, below line will depend on your logic and code. String jarFileName = watcherThread.getNewNotifiedFile(); // unlock new jar file. unlockFile(jarFileName); // shutdown JVM System.exit(0); // bash will restart JVM }