6

ディスクストアの永続性を備えたキャッシュを使用しています。その後のアプリの再実行で、次のエラーが発生します。

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"));
    }
}
4

3 に答える 3

13

システムプロパティを設定してみてください: net.sf.ehcache.enableShutdownHook = true

したがって、プログラムの先頭に次の行を追加することもできます。 System.setProperty("net.sf.ehcache.enableShutdownHook","true");

または、コマンドラインからプロパティを渡すには、次のようにします。 java -Dnet.sf.ehcache.enableShutdownHook=true ...

ehcache Webサイトでは、このシャットダウンフックを使用する際に注意が必要です 。Ehcacheのシャットダウン

シャットダウンフックが実行される場合と実行されない場合

シャットダウンフックは次の場合に実行されます。

  • プログラムは正常に存在します。たとえば、System.exit()が呼び出されるか、最後の非デーモンスレッドが終了します
  • 仮想マシンは終了します。例:CTRL-C。これは、Unixシステムのkill-SIGTERMpidまたはkill-15pidに対応します。

シャットダウンフックは、次の場合には実行されません。

  • 仮想マシンが異常終了します
  • SIGKILLシグナルは、Unixシステムの仮想マシンプロセスに送信されます。例:kill-SIGKILLpidまたはkill-9pid
  • TerminateProcess呼び出しは、Windowsシステムのプロセスに送信されます。

それがうまくいくことを願っています:)

于 2010-03-06T18:51:44.507 に答える
2

アプリケーションをどのように停止していますか?

Ehcacheコードを見ると、Runtime.getRuntime().addShutdownHookJVM出口でキャッシュを閉じるJVMシャットダウンフックが登録されています。JVMが強制終了されるかクラッシュした場合、シャットダウンフックは呼び出されません。

コメントを更新してください:

DiskStoreのdisposeメソッドからのコメントは次のとおりです。

キャッシュのシャットダウンに備えてディスクストアをシャットダウンします

VMがクラッシュした場合、シャットダウンフックは実行されません。データファイルとインデックスファイルは同期していません。初期化では、要素を読み取った後は常にインデックスファイルを削除するため、長さはゼロになります。ダーティリスタートでも、データファイルは自動的に削除されるため、安全性が維持されます。

したがって、別の単体テストでキャッシュを再作成する場合。shutdownHookが実行されなかったため、インデックスファイルは0になります。Ehcacheはインデックスが破損していると見なします。各単体テストでJUnitの@Afterアノテーションを使用してキャッシュをシャットダウンします。または、すべてのテストでキャッシュを共有しますが、これでは分離されたテストが得られないと思います。

于 2010-03-03T17:44:29.837 に答える
1

Spring3.1以降およびjavaconfigでEhcacheを使用している場合は、以下を使用する必要があります。

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

(Web以外のSpring ApplicationContextも使用していると仮定して、そこでシャットダウンフックを有効にして、Beanを正常に破棄します。

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

詳細については、これを参照してください。

于 2015-10-06T06:36:02.397 に答える