Диск 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"));
    }
}
6
задан Tomasz 5 March 2010 в 16:38
поделиться

2 ответа

Попробуйте установить системное свойство: net.sf.ehcache.enableShutdownHook = true

Итак, вы можете добавить следующая строка в начале вашей программы: System.setProperty ("net.sf.ehcache.enableShutdownHook", "true");

Или из командной строки для передачи свойства : java -Dnet.sf.ehcache.enableShutdownHook = true ...

Обратите внимание, на веб-сайте ehcache упоминаются некоторые меры предосторожности при использовании этой ловушки выключения: Завершение работы Отключить Ehcache

Когда ловушка выключения будет запущена, а когда нет

Ловушка выключения запускается, когда:

  • программа существует нормально. например Вызывается System.exit (), или последний не-демонный поток завершает работу
  • , виртуальная машина завершается. например CTRL-C. Это соответствует kill -SIGTERM pid или kill -15 pid в системах Unix.

Ловушка выключения не будет работать, если:

  • Виртуальная машина прерывает работу
  • Сигнал SIGKILL отправляется процессу виртуальной машины в системах Unix. например kill -SIGKILL pid или kill -9 pid
  • Вызов TerminateProcess отправляется процессу в системах Windows.

Надеюсь, это сработает :)

13
ответ дан 8 December 2019 в 16:01
поделиться

Как вы останавливаете свое приложение?

Судя по коду Ehcache, он регистрирует хук выключения JVM Runtime.getRuntime().addShutdownHook, который закрывает кэш при выходе JVM. Если JVM будет убита, или произойдет крах, крючок закрытия не будет вызван.

Обновление комментария RE:

Вот комментарий метода DiskStore dispose:

Выключает дисковое хранилище в рамках подготовки к выключению кэша

Если произойдет крах виртуальной машины, хук выключения не будет запущен. Файл данных и индексный файл будут не синхронизированы. При инициализации мы всегда удаляем индексный файл после чтения элементов, так что его длина равна нулю. При грязном перезапуске он все равно будет иметь ее, а файл данных будет автоматически удален, что сохранит безопасность.

Итак, если вы воссоздаете кэш в другом модульном тесте. Поскольку shutdownHook не был бы запущен, индексный файл будет равен 0. Ehcache думает, что индекс поврежден. Я бы отключил кэш с помощью аннотации JUnit @After в каждом из ваших юнит-тестов. Или разделить кэш на все тесты, но я предполагаю, что это не даст вам изолированных тестов.

2
ответ дан 8 December 2019 в 16:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: