Ehcache磁盘存储不干净关机

我正在使用具有磁盘存储持久性的缓存。 在应用程序的后续重新运行中,我收到以下错误:

net.sf.ehcache.store.DiskStore deleteIndexIfCorrupt WARNING: The index for data file MyCache.data is out of date, probably due to an unclean shutdown. Deleting index file MYCache.index 

除了在应用程序中的某处显式调用net.sf.ehcache.CacheManager.shutdown()之外,还有什么方法可以解决这个问题吗?

缓存配置:

        

用于复制问题的代码:

 import java.util.ArrayList; import java.util.List; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; public class CacheTest { static CacheManager manager = new CacheManager(CacheTest.class .getResource("ehcache.xml")); static Cache cache; public static void main(String[] args) { // Get a default instance manager.addCache("test"); cache = manager.getCache("test"); // Generate some junk so that the // cache properly flushes to disk // as cache.flush() is not working List t = new ArrayList(); for (int i = 0; i < 1000; i++) t.add(null); // Oddly enough fewer elements // do not persist to disk or give // an error for (int i = 0; i < 100000; i++) { cache.put(new Element(i, t)); } cache.flush(); if (cache.get("key1") == null) { System.out.println("key1 not found in cache!"); cache.put(new Element("key1", "value1")); } System.out.println(cache.get("key1")); } } 

尝试设置系统属性: net.sf.ehcache.enableShutdownHook = true

因此,您可以在程序开头添加以下行: System.setProperty("net.sf.ehcache.enableShutdownHook","true");

或者,从命令行传递属性: java -Dnet.sf.ehcache.enableShutdownHook=true ...

注意,ehcache网站在使用此关闭钩子时确实提到了一些注意事项: 关闭Ehcache

当一个关闭钩子运行时,它什么时候不运行

关闭钩子运行时:

  • 程序通常存在。 例如,调用System.exit(),或者退出最后一个非守护进程线程
  • 虚拟机终止。 例如CTRL-C。 这对应于Unix系统上的kill -SIGTERM pid或kill -15 pid。

在以下情况下,关闭钩子不会运行:

  • 虚拟机中止
  • SIGKILL信号被发送到Unix系统上的虚拟机进程。 例如杀死-SIGKILL pid或kill -9 pid
  • TerminateProcess调用将发送到Windows系统上的进程。

希望它有效:)

你是如何停止申请的?

从查看Ehcache代码,它注册了一个JVM关闭钩子Runtime.getRuntime().addShutdownHook ,用于关闭JVM出口上的缓存。 如果JVM被杀死或崩溃,则不会调用关闭挂钩。

更新你的评论:

以下是DiskStore dispose方法的注释:

关闭磁盘存储以准备缓存关闭

如果发生VM崩溃,则不会运行关闭挂钩。 数据文件和索引文件将不同步。 初始化时,我们总是在读完元素后删除索引文件,使其长度为零。 在脏重启时,它仍然会有,并且数据文件将自动删除,从而保持安全。

因此,如果您在另一个unit testing中重新创建Cache。 由于shutdownHook不会运行,索引文件将为0. Ehcache认为索引已损坏。 我会在每个unit testing中使用JUnit的@After注释关闭Cache。 或者,在所有测试中共享缓存,但我猜这不会给你孤立的测试。

对于我们这些使用Ehcache with Spring 3.1+和java config的人,你必须使用:

 @Bean(destroyMethod = "shutdown") public net.sf.ehcache.CacheManager ehCacheManager() { .. } 

并且(假设您还使用非Web Spring ApplicationContext,在那里启用shutdown钩子以使bean被优雅地销毁:

 context = new AnnotationConfigApplicationContext(AppConfig.class); ((AbstractApplicationContext) context).registerShutdownHook(); 

有关更多信息,请参阅此