2010-03-03 100 views
5

我使用的是磁盤儲存持久性的緩存。在應用程序的後續重播,我發現了以下錯誤:的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()地方解決,除了?

緩存配置:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="ehcache.xsd" 
      updateCheck="true" monitoring="autodetect"> 

    <diskStore path="C:\work"/> 

    <cacheManagerEventListenerFactory class="" properties=""/> 

    <cacheManagerPeerProviderFactory 
      class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory" 
      properties="peerDiscovery=automatic, 
         multicastGroupAddress=230.0.0.1, 
         multicastGroupPort=4446, timeToLive=1" 
      propertySeparator="," 
      /> 

    <cacheManagerPeerListenerFactory 
      class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/> 

    <defaultCache 
      maxElementsInMemory="1" 
      eternal="false" 
      timeToIdleSeconds="0" 
      timeToLiveSeconds="86400" 
      overflowToDisk="true" 
      diskSpoolBufferSizeMB="1" 
      maxElementsOnDisk="10000" 
      diskPersistent="true" 
      diskExpiryThreadIntervalSeconds="120" 
      memoryStoreEvictionPolicy="LFU" 
      /> 

</ehcache> 

代碼複製的問題:

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<String> t = new ArrayList<String>(); 
     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")); 
    } 
} 

回答

12

嘗試設置系統屬性: net.sf.ehcache.enableShutdownHook =真

所以,要麼你可以在你的程序的開頭添加以下行: System.setProperty("net.sf.ehcache.enableShutdownHook","true");

或者,從命令行通過屬性: java -Dnet.sf.ehcache.enableShutdownHook=true ...

請注意,ehcache網站在使用此關機掛鉤時確實提到了一些注意事項: Shutting Down Ehcache

When a shutdown hook will run, and when it will not

The shutdown hook runs when:

  • a program exists normally. e.g. System.exit() is called, or the last non-daemon thread exits
  • the Virtual Machine is terminated. e.g. CTRL-C. This corresponds to kill -SIGTERM pid or kill -15 pid on Unix systems.

The shutdown hook will not run when:

  • the Virtual Machine aborts
  • A SIGKILL signal is sent to the Virtual Machine process on Unix systems. e.g. kill -SIGKILL pid or kill -9 pid
  • A TerminateProcess call is sent to the process on Windows systems.

希望工程:)

+0

耶,工作。謝謝! :) – Tomasz 2010-03-07 17:53:25

2

你如何阻止你的應用程序?

從看的Ehcache代碼,它會註冊一個JVM關閉掛鉤Runtime.getRuntime().addShutdownHook封閉在JVM退出緩存。如果JVM被終止或崩潰,關閉鉤子將不會被調用。

更新RE您的評論:

下面是從DiskStore dispose方法的註釋:

Shuts down the disk store in preparation for cache shutdown

If a VM crash happens, the shutdown hook will not run. The data file and the index file will be out of synchronisation. At initialisation we always delete the index file after we have read the elements, so that it has a zero length. On a dirty restart, it still will have and the data file will automatically be deleted, thus preserving safety.

所以,如果你重新創建緩存在不同的單元測試。由於shutdownHook不會跑,索引文件將是0的Ehcache認爲該指數已損壞。我會在每個單元測試中使用JUnit的@After註釋關閉緩存。或者,在所有測試中共享緩存,但我猜這不會給你孤立的測試。

+0

我運行它作爲一個Junit4測試的一部分。該錯誤顯示在隨後重新運行測試。如果有幫助,我可以提供一個代碼示例進行復制。 – Tomasz 2010-03-04 10:39:15

+0

我更新基於您的評論的問題。 – 2010-03-04 13:44:24

+0

nope,即使從可運行jar中的命令行運行,仍然會出現相同的錯誤。 – Tomasz 2010-03-05 13:38:22

0

對於我們這些使用了Ehcache與Spring 3.1+和Java的配置,你必須使用:

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

和(假設你也使用非web的Spring ApplicationContext,啓用關閉鉤子,使bean正常銷燬:

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

看到this以獲取更多信息。