This is a book about ehcache, a widely used open source Java cache. Ehcache has grown in size and scope since it was introduced in October 2003. As people used it they often noticed it was missing a feature they wanted. Over time, the features that were repeatedly asked for, and make sense for a Cache, have been added.
Ehcache is now used for Hibernate caching, data access object caching, security credential caching, web caching, application persistence and distributed caching. The biggest issue faced by Ehcache users at the time of writing is understanding when and how to use these features.
This book is for Ehcache version 1.4.0.
The intended audience for this book is developers who use ehcache. It should be able to be used to start from scratch, get up and running quickly, and also be useful for the more complex options.
Ehcache is about performance and load reduction of underlying resources. Another natural audience is performance specialists.
It is also intended for application and enterprise architects. Some of the features of ehcache, such as distributed caching and Java EE caching, are alternatives to be considered along with other ways of solving those problems. This book discusses the trade-offs in ehcache's approach to help make a decision about appropriateness of use.
The PDF is designed to be printed, with blank pages deliberately left to maintiain book conventions.
Ehcache has had many contributions in the form of forum discussions, feature requests, bug reports, patches and code commits.
Rather than try and list the many hundreds of people who have contributed to ehcache in some way it is better to link to the web site where contributions are acknowledged in the following ways:
Thanks to Denis Orlov for suggesting the need for a book in the first place.

Adam Murdoch (an all round top Java coder) came up with the name in a moment of inspiration while we were stuck on the SourceForge project create page. Ehcache is a palindrome. He thought the name was wicked cool and we agreed.
The logo is similarly symmetrical, and is evocative of the diagram symbol for a doubly-linked list. That structure lies at the heart of ehcache.
Ehcache is a cache library. Before getting into ehcache, it is worth stepping back and thinking about caching generally.
Wiktionary defines a cache as A store of things that will be required in future, and can be retrieved rapidly. That is the nub of it.
In computer science terms, a cache is a collection of temporary data which either duplicates data located elsewhere or is the result of a computation. Once in the cache, the data can be repeatedly accessed inexpensively.
While ehcache concerns itself with Java objects, caching is used throughout computing, from CPU caches to the DNS system. Why? Because many computer systems exhibit locality of reference. Data that is near other data or has just been used is more likely to be used again.
Chris Anderson, of Wired Magazine, coined the term The Long Tail to refer to Ecommerce systems. The idea that a small number of items may make up the bulk of sales, a small number of blogs might get the most hits and so on. While there is a small list of popular items, there is a long tail of less popular ones.

The Long Tail
The Long Tail is itself a vernacular term for a Power Law probability distribution. They don't just appear in ecommerce, but throughout nature. One form of a Power Law distribution is the Pareto distribution, commonly know as the 80:20 rule.
This phenomenon is useful for caching. If 20% of objects are used 80% of the time and a way can be found to reduce the cost of obtaining that 20%, then the system performance will improve.
The short answer is that it often does, due to the effects noted above.
The medium answer is that it often depends on whether it is CPU bound or I/O bound. If an application is I/O bound then then the time taken to complete a computation depends principally on the rate at which data can be obtained. If it is CPU bound, then the time taken principally depends on the speed of the CPU and main memory.
While the focus for caching is on improving performance, it it also worth realizing that it reduces load. The time it takes something to complete is usually related to the expense of it. So, caching often reduces load on scarce resources.
CPU bound applications are often sped up by:
The role of caching, if there is one, is to temporarily store computations that may be reused again.
An example from ehcache would be large web pages that have a high rendering cost. Another caching of authentication status, where authentication requires cryptographic transforms.
Many applications are I/O bound, either by disk or network operations. In the case of databases they can be limited by both.
There is no Moore's law for hard disks. A 10,000 RPM disk was fast 10 years ago and is still fast. Hard disks are speeding up by using their own caching of blocks into memory.
Network operations can be bound by a number of factors:
The caching of data can often help a lot with I/O bound applications. Some examples of ehcache uses are:
The flip side of increased performance is increased scalability. Say you have a database which can do 100 expensive queries per second. After that it backs up and if connections are added to it it slowly dies.
In this case, caching may be able to reduce the workload required. If caching can cause 90 of that 100 to be cache hits and not even get to the database, then the database can scale 10 times higher than otherwise.
The short answer is that it depends on a multitude of factors being:
In applications that are I/O bound, which is most business applications, most of the response time is getting data from a database. Therefore the speed up mostly depends on how much reuse a piece of data gets.
In a system where each piece of data is used just once, it is zero. In a system where data is reused a lot, the speed up is large.
The long answer, unfortunately, is complicated and mathematical. It is considered next.
Amdahl's law, after Gene Amdahl, is used to find the system speed up from a speed up in part of the system.
1 / ((1 - Proportion Sped Up) + Proportion Sped Up / Speed up)
The following examples show how to apply Amdahl's law to common situations. In the interests of simplicity, we assume:
A Hibernate Session.load() for a single object is about 1000 times faster from cache than from a database.
A typical Hibernate query will return a list of IDs from the database, and then attempt to load each. If Session.iterate() is used Hibernate goes back to the database to load each object.
Imagine a scenario where we execute a query against the database which returns a hundred IDs and then load each one.
The query takes 20% of the time and the roundtrip loading takes the rest (80%). The database query itself is 75% of the time that the operation takes. The proportion being sped up is thus 60% (75% * 80%).
The expected system speedup is thus:
1 / ((1 - .6) + .6 / 1000)
= 1 / (.4 + .006)
= 2.5 times system speedupAn observed speed up from caching a web page is 1000 times. Ehcache can retrieve a page from its SimplePageCachingFilter in a few ms.
Because the web page is the end result of a computation, it has a proportion of 100%.
The expected system speedup is thus:
1 / ((1 - 1) + 1 / 1000)
= 1 / (0 + .001)
= 1000 times system speedupCaching the entire page is a big win. Sometimes the liveness requirements vary in different parts of the page. Here the SimplePageFragmentCachingFilter can be used.
Let's say we have a 1000 fold improvement on a page fragment that taking 40% of the page render time.
The expected system speedup is thus:
1 / ((1 - .4) + .4 / 1000)
= 1 / (6 + .004)
= 1.6 times system speedupIn real life cache entrie do not live forever. Some examples that come close are "static" web pages or fragments of same, like page footers, and in the database realm, reference data, such as the currencies in the world.
Factors which affect the efficiency of a cache are:
Ehcache keeps these statistics for each Cache and each element, so they can be measured directly rather than estimated.
Also in real life, we generally do not find a single server?
Assume a round robin load balancer where each hit goes to the next server.
The cache has one entry which has a variable lifespan of requests, say caused by a time to live. The following table shows how that lifespan can affect hits and misses.
Server 1 Server 2 Server 3 Server 4 M M M M H H H H H H H H H H H H H H H H ... ... ... ...
The cache hit ratios for the system as a whole are as follows:
Entry Lifespan Hit Ratio Hit Ratio Hit Ratio Hit Ratio in Hits 1 Server 2 Servers 3 Servers 4 Servers 2 1/2 0/2 0/2 0/2 4 3/4 2/4 1/4 0/4 10 9/10 8/10 7/10 6/10 20 19/20 18/20 17/20 16/10 50 49/50 48/50 47/20 46/50
The efficiency of a cluster of standalone caches is generally:
(Lifespan in requests - Number of Standalone Caches) / Lifespan in requests
Where the lifespan is large relative to the number of standalone caches, cache efficiency is not much affected.
However when the lifespan is short, cache efficiency is dramatically affected.
(To solve this problem, ehcache supports distributed caching, where an entry put in a local cache is also propagated to other servers in the cluster.)
From the above we now have:
1 / ((1 - Proportion Sped Up * effective cache efficiency) + (Proportion Sped Up * effective cache efficiency)/ Speed up)
effective cache efficiency = cache efficiency * cluster efficiency
Applying this to the earlier web page cache example where we have cache efficiency of 35% and average request lifespan of 10 requests and two servers:
cache efficiency = .35
cluster efficiency = .(10 - 1) / 10
= .9
effective cache efficiency = .35 * .9
= .315
1 / ((1 - 1 * .315) + 1 * .315 / 1000)
= 1 / (.685 + .000315)
= 1.45 times system speedupWhat if, instead the cache efficiency is 70%; a doubling of efficiency. We keep to two servers.
cache efficiency = .70
cluster efficiency = .(10 - 1) / 10
= .9
effective cache efficiency = .70 * .9
= .63
1 / ((1 - 1 * .63) + 1 * .63 / 1000)
= 1 / (.37 + .00063)
= 2.69 times system speedupWhat if, instead the cache efficiency is 90%; a doubling of efficiency. We keep to two servers.
cache efficiency = .90
cluster efficiency = .(10 - 1) / 10
= .9
effective cache efficiency = .9 * .9
= .81
1 / ((1 - 1 * .81) + 1 * .81 / 1000)
= 1 / (.19 + .00081)
= 5.24 times system speedupWhy is the reduction so dramatic? Because Amdahl's law is most sensitive to the proportion of the system that is sped up.
Ehcache can be used directly. It can also be used with the popular Hibernate Object/Relational tool. Finally, it can be used for Java EE Servlet Caching.
This quick guide gets you started on each of these. The rest of the documentation can be explored for a deeper understanding.
See Code Samples for more information on direct interaction with ehcache.
See Hibernate Caching for more information.
See Java EE Servlet Caching for more information.
Ehcache contains an early draft implementation of JCache contained in the net.sf.ehcache.jcache package.
See the JSR107 chapter for usage.
Usually, with these, you are using ehcache without even realising it. The first steps in getting more control over what is happening are:
Over the years, various performance tests have shown ehcache to be one of the fastest Java caches. Ehcache's threading is designed for large, high concurrency systems.
Extensive performance tests in the test suite keep ehcache's performance consistent between releases.
As an example, some guys have created a java cache test tool called cache4j_perfomance_tester.
The results for ehcache-1.1 and ehcache-1.2 follow.
ehcache-1.1 [java] --------------------------------------------------------------- [java] java.version=1.4.2_09 [java] java.vm.name=Java HotSpot(TM) Client VM [java] java.vm.version=1.4.2-54 [java] java.vm.info=mixed mode [java] java.vm.vendor="Apple Computer, Inc." [java] os.name=Mac OS X [java] os.version=10.4.5 [java] os.arch=ppc [java] --------------------------------------------------------------- [java] This test can take about 5-10 minutes. Please wait ... [java] --------------------------------------------------------------- [java] |GetPutRemoveT |GetPutRemove |Get | [java] --------------------------------------------------------------- [java] cache4j 0.4 |9240 |9116 |5556 | [java] oscache 2.2 |33577 |30803 |8350 | [java] ehcache 1.1 |7697 |6145 |3395 | [java] jcs 1.2.7.0 |8966 |9455 |4072 | [java] --------------------------------------------------------------- ehcache-1.2 [java] --------------------------------------------------------------- [java] java.version=1.4.2_09 [java] java.vm.name=Java HotSpot(TM) Client VM [java] java.vm.version=1.4.2-54 [java] java.vm.info=mixed mode [java] java.vm.vendor="Apple Computer, Inc." [java] os.name=Mac OS X [java] os.version=10.4.5 [java] os.arch=ppc [java] --------------------------------------------------------------- [java] This test can take about 5-10 minutes. Please wait ... [java] --------------------------------------------------------------- [java] |GetPutRemoveT |GetPutRemove |Get | [java] --------------------------------------------------------------- [java] cache4j 0.4 |9410 |9053 |5865 | [java] oscache 2.2 |28076 |30833 |8031 | [java] ehcache 1.2 |8753 |7072 |3479 | [java] jcs 1.2.7.0 |8806 |9522 |4097 | [java] ---------------------------------------------------------------
Many users of ehcache hardly know they are using it. Sensible defaults require no initial configuration.
The API is very simple and easy to use, making it possible to get up and running in minutes. See the Code Samples for details.
Ehcache 1.2 is 110KB making it convenient to package.
Commons logging and collections are the only dependencies for most JDKs.
The largest ehcache installations use memory and disk stores in the gigabyte range. Ehcache is tuned for these large sizes.
The largest ehcache installations use hundreds of caches.
There is a tension between thread safety and performance. Ehcache's threading started off coarse-grained, but has increasingly made use of ideas from Doug Lea to achieve greater performance. Over the years there have been a number of scalability bottlenecks identified and fixed.
Ehcache 1.2 introduced multiple CacheManagers per virtual machine. This enables completely difference ehcache.xml configurations to be applied.
As of ehcache-1.2 there is an API for Objects in addition to the one for Serializable. Non-serializable Objects can use all parts of ehcache except for DiskStore and replication. If an attempt is made to persist or replicate them they are discarded and a WARNING level log message emitted.
The APIs are identical except for the return methods from Element. Two new methods on Element: getObjectValue and getKeyValue are the only API differences between the Serializable and Object APIs. This makes it very easy to start with caching Objects and then change your Objects to Seralizable to participate in the extra features when needed. Also a large number of Java classes are simply not Serializable.
Time to lives and time to idles are settable per cache. In addition, from ehcache-1.2.1, overrides to these can be set per Element.
Ehcache 1.2 introduced Less Frequently Used and First In First Out caching eviction policies. These round out the eviction policies.
Ehcache, like most of the cache solutions, provides high performance memory and disk stores.
Flexible, extensible, high performance distributed caching. The default implementation supports cache discovery via multicast or manual configuration. Updates are delivered either asynchronously or synchronously via custom RMI connections. Additional discovery or delivery schemes can be plugged in by third parties.
See the Distributed Caching documentation for more feature details.
Ehcache offers the the most complete implementation of JSR107 JCACHE to date.
Because JCACHE has not yet been released the JCACHE API that Ehcache implements has been released as net.sf.jsr107cache.
Implementers can code to the JCACHE API which will create portability to other caching solutions in the future.
The maintainer of ehcache, Greg Luck, is on the expert committee for JSR107.
Ehcache 1.2 provides CacheManagerEventListener and CacheEventListener interfaces. Implementations can be plugged in and configured in ehcache.xml.
Distributed caching, introduced in ehcache 1.2 involves many choices and tradeoffs. The ehcache team believe that one size will not fit all. Implementers can use built-in mechanisms or write their own. A plugin development guide is included for this purpose.
Create your own Cache Extensions, which hold a reference to a cache and are bound to its lifecycle.
Create your own Cache Loaders, which are general purpose asynchronous methods for loading data into caches, or use them in pull-through configuration.
Create an Exception Handler which is invoked if any Exception occurs on a cache operation.
With ehcache 1.1 in 2004, ehcache was the first open source Java cache to introduce persistent storage of cache data on disk on shutdown. The cached data is then accessible the next time the application runs.
With ehcache 1.2, the flushing of entries to disk can be executed with a cache.flush() method whenever required, making it easier to use ehcache
Register Cache Manager listeners through the CacheManagerEventListener interface with the following event methods:
Register Cache Event Listeners through the CacheEventListener interfaces, which provides a lot of flexibility for post-processing of cache events. The methods are:
Ehcache is JMX enabled. You can monitor and manage the following MBeans:
See the net.sf.ehcache.management package.
See http://weblogs.java.net/blog/maxpoon/archive/2007/06/extending_the_n_2.html for an online tutorial.
Ehcache 1.2 introduced a full-featured, fine-grained distributed caching mechanism for clusters.
Peer discovery may be either manually configured or automatic, using multicast. Multicast is simple, and adds and removes peers automatically. Manual configuration gives fine control and is useful for situations where multicast is blocked.
The built-in delivery mechanism uses RMI with custom sockets over TCP, not UDP.
Replication can be set to synchronous Or asynchronous, per cache.
Replication can be set to copy or invalidate, per cache, as is appropriate.
No programming changes are required to make use of replication. Only configuration in ehcache.xml.
Distributed caching, introduced in ehcache 1.2 involves many choices and tradeoffs. The ehcache team believe that one size will not fit all. Implementers can use built-in mechanisms or write their own. A plugin development guide is included for this purpose.
Distributed caches enter and leave the cluster at different times. Caches can be configured to bootstrap themselves from the cluster when they are first initialized.
An abstract factory, BootstrapCacheLoaderFactory has been defined along with an interface BootstrapCacheLoader along with an RMI based default implementation.
High quality implementations for common caching scenarios and patterns.
A cache which blocks subsequent threads until the first read thread populates a cache entry.
SelfPopulatingCache - a read-through cache. A cache that populates elements as they are requested without requiring the caller to know how the entries are populated. It also enables refreshes of cache entries without blocking reads on the same entries.
A high performance Java EE servlet filter that caches pages based on the request URI and Query String. It also gzips the pages and delivers them to browsers either gzipped or ungzipped depending on the HTTP request headers. Use to cache entire Servlet pages, whether from JSP, velocity, or any other rendering technology.
Tested with Orion and Tomcat.
A high performance Java EE filter that caches page fragments based on the request URI and Query String. Use with Servlet request dispatchers to cache parts of pages, whether from JSP, velocity, or any other rendering technology. Can be used from JSPs using jsp:include.
Tested with Orion and Tomcat.
This is the trusty old command pattern with a twist: asynchronous behaviour, fault tolerance and caching. Creates a command, caches it and then attempts to execute it.
Tested with Hibernate2.1.8 and Hibernate3.1.3, which can utilise all of the new features except for Object API and multiple session factories each using a different ehcache CacheManager.
A new net.sf.ehcache.hibernate.EhCacheProvider makes those additional features available to Hibernate-3.1.3. A version of the new provider should make it into the Hibernate3.2 release.
The ehcache team believe that the first and most important quality measure is a well designed and comprehensive test suite.
Ehcache has a relatively high 86% test coverage of source code. This has edged higher over time. Clover enforces the test coverage. Most of the missing 14% is logging and exception paths.
The ehcache JUnit test suite contains some long-running system tests which place high load on different ehcache subsystems to the point of failure and then are back off to just below that point. The same is done with limits such as the amount of Elements that can fit in a given heap size. The same is also done with performance testing of each subsystem and the whole together. The same is also done with network tests for cache replication.
The tests serve a number of purposes:
Ehcache also has concurrency testing, which typically uses 50 concurrent threads hammering a piece of code. The test suites are also run on multi-core or multi-cpu machines so that concurrency is real rather than simulated. Additionally, every concurrency related issue that has ever been anticipated or resulted in a bug report has a unit test which prevents the condition from recurring. There are no reported issues that have not been reproduced in a unit test.
Concurrency unit tests are somewhat difficult to write, and are often overlooked. The team considers these tests a major factor in ehcache's quality.
Ehcache came about in the first place because of production issues with another open source cache.
Final release versions of ehcache have been production tested on a very busy e-commerce site, supporting thousands of concurrent users, gigabyte size caches on large multi-cpu machines. It has been the experience of the team that most threading issues do not surface until this type of load has been applied. Once an issue has been identified and investigated a concurrency unit test can then be crafted.
A core belief held by the project team is that a project needs good documentation to be useful.
In ehcache, this is manifested by:
Ehcache is used extensively. See the Who is Using? page, or browse Google.
Projects like Linux maintain their quality through a restricted change process, whereby changes are submitted as patches, then reviewed by the maintainer and included, or modified. Ehcache follows the same process.
Through the SourceForge project bug tracker, the full history of all bugs are shown, including current status. We take this for granted in an open source project, as this is typically a feature that all open source projects have, but this transparency makes it possible to gauge the quality and riskiness of a library, something not usually possible in commercial products.
The ehcache team is serious about quality. If one user is having a problem, it probably means others are too, or will have. The ehcache team use ehcache themselves in production. Every effort will be made to provide fixes for serious production problems as soon as possible. These will be committed to trunk. From there an affected user can apply the fix to their own branch.
Ehcache's original Apache1.1 copyright and licensing was reviewed and approved by the Apache Software Foundation, making ehcache suitable for use in Apache projects. ehcache-1.2 is released under the updated Apache 2.0 license.
The Apache license is also friendly one, making it safe and easy to include ehcache in other open source projects or commercial products.

Top Level Package Diagram
Ehcache consists of a CacheManager, which manages caches. Caches contain elements, which are essentially name value pairs. Caches are physically implemented either in-memory, or on disk.

CacheManager Class Diagram
The CacheManager comprises Caches which in turn comprise Elements.
Creation of, access to and removal of caches is controlled by the CacheManager.
CacheManager supports two creation modes: singleton and instance.
Ehcache-1.1 supported only one CacheManager instance which was a singleton. CacheManager can still be used in this way using the static factory methods.
From ehcache-1.2, CacheManager has constructors which mirror the various static create methods. This enables multiple CacheManagers to be created and used concurrently. Each CacheManager requires its own configuration.
If the Caches under management use only the MemoryStore, there are no special considerations. If Caches use the DiskStore, the diskStore path specified in each CacheManager configuration should be unique. When a new CacheManager is created, a check is made that there are no other CacheManagers using the same diskStore path. If there are, a CacheException is thrown. If a CacheManager is part of a cluster, there will also be listener ports which must be unique.
If an application creates instances of CacheManager using a constructor, and also calls a static create method, there will exist a singleton instance of CacheManager which will be returned each time the create method is called together with any other instances created via constructor. The two types will coexist peacefully.

Ehcache Interface Diagram
All caches implement the Ehcache interface. A cache has a name and attributes. Each cache contains Elements.
A Cache in ehcache is analogous to a cache region in other caching systems.
Cache elements are stored in the MemoryStore. Optionally they also overflow to a DiskStore.

Element Class Diagram
An element is an atomic entry in a cache. It has a key, a value and a record of accesses. Elements are put into and removed from caches. They can also expire and be removed by the Cache, depending on the Cache settings.
As of ehcache-1.2 there is an API for Objects in addition to the one for Serializable. Non-serializable Objects can use all parts of ehcache except for DiskStore and replication. If an attempt is made to persist or replicate them they are discarded without error and with a DEBUG level log message.
The APIs are identical except for the return methods from Element. Two new methods on Element: getObjectValue and getKeyValue are the only API differences between the Serializable and Object APIs. This makes it very easy to start with caching Objects and then change your Objects to Seralizable to participate in the extra features when needed. Also a large number of Java classes are simply not Serializable.
Caches can be used in different ways. Each of these ways follows a cache usage pattern. Ehcache supports the following:
Here, to put something in the cache you do cache.put(Element element) and to get something from the cache you do cache.get(Object key).
You are aware you are using a cache and you are doing so consciously.
Here, you just do gets to the cache using cache.get(Object key). The cache itself knows how to populate an entry.
See the SelfPopulatingCache for more on this pattern.
Caches can be configured in ehcache either declaratively, in xml, or by creating them programmatically and specifying their parameters in the constructor.
While both approaches are fully supported it is generally a good idea to separate the cache configuration from runtime use. There are also these benefits:
This chapter covers XML declarative configuration. See the Code samples for programmatic configuration.
Ehcache is redistributed by lots of projects. They may or may not provide a sample ehcache XML configuration file. If one is not provided, download ehcache from http://ehcache.sf.net. It, and the ehcache.xsd is provided in the distribution.
Ehcache configuration files must be comply with the ehcache XML schema, ehcache.xsd, reproduced below.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="ehcache" >
<xs:complexType>
<xs:sequence>
<xs:element ref="diskStore"/>
<xs:element minOccurs="0" maxOccurs="1"
ref="cacheManagerEventListenerFactory"/>
<xs:element minOccurs="0" maxOccurs="1"
ref="cacheManagerPeerProviderFactory"/>
<xs:element minOccurs="0" maxOccurs="1"
ref="cacheManagerPeerListenerFactory"/>
<xs:element ref="defaultCache"/>
<xs:element maxOccurs="unbounded" ref="cache"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="diskStore">
<xs:complexType>
<xs:attribute name="path" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="cacheManagerEventListenerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheManagerPeerProviderFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheManagerPeerListenerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<!-- add clone support for addition of cacheExceptionHandler. Important! -->
<xs:element name="defaultCache">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheLoaderFactory"/>
</xs:sequence>
<xs:attribute name="diskExpiryThreadIntervalSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="diskSpoolBufferSizeMB" use="optional" type="xs:integer"/>
<xs:attribute name="diskPersistent" use="optional" type="xs:boolean"/>
<xs:attribute name="eternal" use="required" type="xs:boolean"/>
<xs:attribute name="maxElementsInMemory" use="required" type="xs:integer"/>
<xs:attribute name="memoryStoreEvictionPolicy" use="optional" type="xs:string"/>
<xs:attribute name="overflowToDisk" use="required" type="xs:boolean"/>
<xs:attribute name="timeToIdleSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="timeToLiveSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="maxElementsOnDisk" use="optional" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element name="cache">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
<xs:element minOccurs="0" maxOccurs="1" ref="cacheLoaderFactory"/>
</xs:sequence>
<xs:attribute name="diskExpiryThreadIntervalSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="diskSpoolBufferSizeMB" use="optional" type="xs:integer"/>
<xs:attribute name="diskPersistent" use="optional" type="xs:boolean"/>
<xs:attribute name="eternal" use="required" type="xs:boolean"/>
<xs:attribute name="maxElementsInMemory" use="required" type="xs:integer"/>
<xs:attribute name="memoryStoreEvictionPolicy" use="optional" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="overflowToDisk" use="required" type="xs:boolean"/>
<xs:attribute name="timeToIdleSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="timeToLiveSeconds" use="optional" type="xs:integer"/>
<xs:attribute name="maxElementsOnDisk" use="optional" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheEventListenerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="bootstrapCacheLoaderFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheExtensionFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheExceptionHandlerFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="cacheLoaderFactory">
<xs:complexType>
<xs:attribute name="class" use="required"/>
<xs:attribute name="properties" use="optional"/>
<xs:attribute name="propertySeparator" use="optional"/>
</xs:complexType>
</xs:element>
</xs:schema>If the CacheManager default constructor or factory method is called, ehcache looks for a file called ehcache.xml in the top level of the classpath. Failing that it looks for ehcache-failsafe.xml in the classpath. ehcache-failsafe.xml is packaged in the ehcache jar and should always be found.
ehcache-failsafe.xml provides an extremely simple default configuration to enable users to get started before they create their own ehcache.xml.
If it used ehcache will emit a warning, reminding the user to set up a proper configuration.
The meaning of the elments and attributes are explained in the section on ehcache.xml. --- ehcache diskStore path="java.io.tmpdir"/ defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" / /ehcache ---
If the CacheManager default constructor or factory method is called, ehcache looks for a file called ehcache.xml in the top level of the classpath.
The non-default creation methods allow a configuration file to be specified which can be called anything.
One XML configuration is required for each CacheManager that is created. It is an error to use the same configuration, because things like directory paths and listener ports will conflict. Ehcache will attempt to resolve conflicts and will emit a warning reminding the user to configure a separate configuration for multiple CacheManagers with conflicting settings.
The sample ehcache.xml, which is included in the ehcache distribution is reproduced below:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<!--
CacheManager Configuration
==========================
An ehcache.xml corresponds to a single CacheManager.
See instructions below or the ehcache schema (ehcache.xsd) on how to configure.
DiskStore configuration
=======================
Sets the path to the directory where cache files are created.
If the path is a Java System Property it is replaced by its value in the
running VM.
The following properties are translated:
* user.home - User's home directory
* user.dir - User's current working directory
* java.io.tmpdir - Default temp file path
Subdirectories can be specified below the property e.g. java.io.tmpdir/one
-->
<diskStore path="java.io.tmpdir"/>
<!--
CacheManagerEventListener
=========================
Specifies a CacheManagerEventListenerFactory, be used to create a CacheManagerPeerProvider,
which is notified when Caches are added or removed from the CacheManager.
The attributes of CacheManagerEventListenerFactory are:
* class - a fully qualified factory class name
* properties - comma separated properties having meaning only to the factory.
Sets the fully qualified class name to be registered as the CacheManager event listener.
The events include:
* adding a Cache
* removing a Cache
Callbacks to listener methods are synchronous and unsynchronized. It is the responsibility
of the implementer to safely handle the potential performance and thread safety issues
depending on what their listener is doing.
If no class is specified, no listener is created. There is no default.
-->
<cacheManagerEventListenerFactory class="" properties=""/>
<!--
CacheManagerPeerProvider
========================
(Enable for distributed operation)
Specifies a CacheManagerPeerProviderFactory which will be used to create a
CacheManagerPeerProvider, which discovers other CacheManagers in the cluster.
The attributes of cacheManagerPeerProviderFactory are:
* class - a fully qualified factory class name
* properties - comma separated properties having meaning only to the factory.
Ehcache comes with a built-in RMI-based distribution system with two means of discovery of
CacheManager peers participating in the cluster:
* automatic, using a multicast group. This one automatically discovers peers and detects
changes such as peers entering and leaving the group
* manual, using manual rmiURL configuration. A hardcoded list of peers is provided at
configuration time.
Configuring Automatic Discovery:
Automatic discovery is configured as per the following example:
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32"/>
Valid properties are:
* peerDiscovery (mandatory) - specify "automatic"
* multicastGroupAddress (mandatory) - specify a valid multicast group address
* multicastGroupPort (mandatory) - specify a dedicated port for the multicast heartbeat
traffic
* timeToLive - specify a value between 0 and 255 which determines how far the packets will
propagate.
By convention, the restrictions are:
0 - the same host
1 - the same subnet
32 - the same site
64 - the same region
128 - the same continent
255 - unrestricted
Configuring Manual Discovery:
Manual discovery is configured as per the following example:
<cacheManagerPeerProviderFactory class=
"net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server1:40000/sampleCache1|//server2:40000/sampleCache1
| //server1:40000/sampleCache2|//server2:40000/sampleCache2"
propertySeparator="," />
Valid properties are:
* peerDiscovery (mandatory) - specify "manual"
* rmiUrls (mandatory) - specify a pipe separated list of rmiUrls, in the form
//hostname:port
The hostname is the hostname of the remote CacheManager peer. The port is the listening
port of the RMICacheManagerPeerListener of the remote CacheManager peer.
-->
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic,
multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=1"
propertySeparator=","
/>
<!--
CacheManagerPeerListener
========================
(Enable for distributed operation)
Specifies a CacheManagerPeerListenerFactory which will be used to create a
CacheManagerPeerListener, which
listens for messages from cache replicators participating in the cluster.
The attributes of cacheManagerPeerListenerFactory are:
class - a fully qualified factory class name
properties - comma separated properties having meaning only to the factory.
Ehcache comes with a built-in RMI-based distribution system. The listener component is
RMICacheManagerPeerListener which is configured using
RMICacheManagerPeerListenerFactory. It is configured as per the following example:
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=fully_qualified_hostname_or_ip,
port=40001,
socketTimeoutMillis=120000"
propertySeparator="," />
All properties are optional. They are:
* hostName - the hostName of the host the listener is running on. Specify
where the host is multihomed and you want to control the interface over which cluster
messages are received. Defaults to the host name of the default interface if not
specified.
* port - the port the listener listens on. This defaults to a free port if not specified.
* socketTimeoutMillis - the number of ms client sockets will stay open when sending
messages to the listener. This should be long enough for the slowest message.
If not specified it defaults 120000ms.
-->
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"/>
<!--
Cache configuration
===================
The following attributes are required.
name:
Sets the name of the cache. This is used to identify the cache. It must be unique.
maxElementsInMemory:
Sets the maximum number of objects that will be created in memory
maxElementsOnDisk:
Sets the maximum number of objects that will be maintained in the DiskStore
The default value is zero, meaning unlimited.
eternal:
Sets whether elements are eternal. If eternal, timeouts are ignored and the
element is never expired.
overflowToDisk:
Sets whether elements can overflow to disk when the memory store
has reached the maxInMemory limit.
The following attributes and elements are optional.
timeToIdleSeconds:
Sets the time to idle for an element before it expires.
i.e. The maximum amount of time between accesses before an element expires
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that an Element can idle for infinity.
The default value is 0.
timeToLiveSeconds:
Sets the time to live for an element before it expires.
i.e. The maximum time between creation time and when an element expires.
Is only used if the element is not eternal.
Optional attribute. A value of 0 means that and Element can live for infinity.
The default value is 0.
diskPersistent:
Whether the disk store persists between restarts of the Virtual Machine.
The default value is false.
diskExpiryThreadIntervalSeconds:
The number of seconds between runs of the disk expiry thread. The default value
is 120 seconds.
diskSpoolBufferSizeMB:
This is the size to allocate the DiskStore for a spool buffer. Writes are made
to this area and then asynchronously written to disk. The default size is 30MB.
Each spool buffer is used only by its cache. If you get OutOfMemory errors consider
lowering this value. To improve DiskStore performance consider increasing it. Trace level
logging in the DiskStore will show if put back ups are occurring.
memoryStoreEvictionPolicy:
Policy would be enforced upon reaching the maxElementsInMemory limit. Default
policy is Least Recently Used (specified as LRU). Other policies available -
First In First Out (specified as FIFO) and Less Frequently Used
(specified as LFU)
Cache elements can also contain sub elements which take the same format of a factory class
and properties. Defined sub-elements are:
* cacheEventListenerFactory - Enables registration of listeners for cache events, such as
put, remove, update, and expire.
* bootstrapCacheLoaderFactory - Specifies a BootstrapCacheLoader, which is called by a
cache on initialisation to prepopulate itself.
* cacheExtensionFactory - Specifies a CacheExtension, a generic mechansim to tie a class
which holds a reference to a cache to the cache lifecycle.
* cacheExceptionHandlerFactory - Specifies a CacheExceptionHandler, which is called when
cache exceptions occur.
* cacheLoaderFactory - Specifies a CacheLoader, which can be used both asynchronously and
synchronously to load objects into a cache.
RMI Cache Replication
Each cache that will be distributed needs to set a cache event listener which replicates
messages to the other CacheManager peers. For the built-in RMI implementation this is done
by adding a cacheEventListenerFactory element of type RMICacheReplicatorFactory to each
distributed cache's configuration as per the following example:
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true,
replicatePuts=true,
replicateUpdates=true,
replicateUpdatesViaCopy=true,
replicateRemovals=true
asynchronousReplicationIntervalMillis=<number of milliseconds"
propertySeparator="," />
The RMICacheReplicatorFactory recognises the following properties:
* replicatePuts=true|false - whether new elements placed in a cache are
replicated to others. Defaults to true.
* replicateUpdates=true|false - whether new elements which override an
element already existing with the same key are replicated. Defaults to true.
* replicateRemovals=true - whether element removals are replicated. Defaults to true.
* replicateAsynchronously=true | false - whether replications are
asynchronous (true) or synchronous (false). Defaults to true.
* replicateUpdatesViaCopy=true | false - whether the new elements are
copied to other caches (true), or whether a remove message is sent. Defaults to true.
* asynchronousReplicationIntervalMillis=<number of milliseconds> - The asynchronous
replicator runs at a set interval of milliseconds. The default is 1000. The minimum
is 10. This property is only applicable if replicateAsynchronously=true
Cluster Bootstrapping
The RMIBootstrapCacheLoader bootstraps caches in clusters where RMICacheReplicators are
used. It is configured as per the following example:
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"
properties="bootstrapAsynchronously=true, maximumChunkSizeBytes=5000000"
propertySeparator="," />
The RMIBootstrapCacheLoaderFactory recognises the following optional properties:
* bootstrapAsynchronously=true|false - whether the bootstrap happens in the background
after the cache has started. If false, bootstrapping must complete before the cache is
made available. The default value is true.
* maximumChunkSizeBytes=<integer> - Caches can potentially be very large, larger than the
memory limits of the VM. This property allows the bootstraper to fetched elements in
chunks. The default chunk size is 5000000 (5MB).
Cache Exception Handling
By default, most cache operations will propagate a runtime CacheException on failure. An
interceptor, using a dynamic proxy, may be configured so that a CacheExceptionHandler can
be configured to intercept Exceptions. Errors are not intercepted.
It is configured as per the following example:
<cacheExceptionHandlerFactory class="com.example.ExampleExceptionHandlerFactory"
properties="logLevel=FINE"/>
Caches with ExceptionHandling configured are not of type Cache, but are of type Ehcache only,
and are not available using CacheManager.getCache(), but using CacheManager.getEhcache().
Cache Loader
A default CacheLoader may be set which loads objects into the cache through asynchronous and
synchronous methods on Cache. This is different to the bootstrap cache loader, which is used
only in distributed caching.
It is configured as per the following example:
<cacheLoaderFactory class="com.example.ExampleCacheLoaderFactory"
properties="type=int,startCounter=10"/>
Cache Extension
CacheExtensions are a general purpose mechanism to allow generic extensions to a Cache.
CacheExtensions are tied into the Cache lifecycle.
CacheExtensions are created using the CacheExtensionFactory which has a
<code>createCacheCacheExtension()</code> method which takes as a parameter a
Cache and properties. It can thus call back into any public method on Cache, including, of
course, the load methods.
Extensions are added as per the following example:
<cacheExtensionFactory class="com.example.FileWatchingCacheRefresherExtensionFactory"
properties="refreshIntervalMillis=18000, loaderTimeout=3000,
flushPeriod=whatever, someOtherProperty=someValue ..."/>
-->
<!--
Mandatory Default Cache configuration. These settings will be applied to caches
created programmtically using CacheManager.add(String cacheName).
The defaultCache has an implicit name "default" which is a reserved cache name.
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
diskSpoolBufferSizeMB="30"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
<!--
Sample caches. Following are some example caches. Remove these before use.
-->
<!--
Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.
If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
maxElementsInMemory="10000"
maxElementsOnDisk="1000"
eternal="false"
overflowToDisk="true"
diskSpoolBufferSizeMB="20"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
/>
<!--
Sample cache named sampleCache2
This cache has a maximum of 1000 elements in memory. There is no overflow to disk, so 1000
is also the maximum cache size. Note that when a cache is eternal, timeToLive and
timeToIdle are not used and do not need to be specified.
-->
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false"
memoryStoreEvictionPolicy="FIFO"
/>
<!--
Sample cache named sampleCache3. This cache overflows to disk. The disk store is
persistent between cache and VM restarts. The disk expiry thread interval is set to 10
minutes, overriding the default of 2 minutes.
-->
<cache name="sampleCache3"
maxElementsInMemory="500"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="1"
memoryStoreEvictionPolicy="LFU"
/>
<!--
Sample distributed cache named sampleDistributedCache1.
This cache replicates using defaults.
It also bootstraps from the cluster, using default properties.
-->
<cache name="sampleDistributedCache1"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="100"
timeToLiveSeconds="100"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"/>
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
</cache>
<!--
Sample distributed cache named sampleDistributedCache2.
This cache replicates using specific properties.
It only replicates updates and does so synchronously via copy
-->
<cache name="sampleDistributedCache2"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="100"
timeToLiveSeconds="100"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=false, replicatePuts=false,
replicateUpdates=true, replicateUpdatesViaCopy=true,
replicateRemovals=false"/>
</cache>
<!--
Sample distributed cache named sampleDistributedCache3.
This cache replicates using defaults except that the asynchronous replication
interval is set to 200ms.
-->
<cache name="sampleDistributedCache3"
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="100"
timeToLiveSeconds="100"
overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="asynchronousReplicationIntervalMillis=200"/>
</cache>
</ehcache>
Ehcache has two stores:
The MemoryStore is always enabled. It is not directly manipulated, but is a component of every cache.
All Elements are suitable for placement in the MemoryStore.
It has the following characteristics:
Thread safe for use by multiple concurrent threads.
Tested for memory leaks. See MemoryCacheTest#testMemoryLeak. This test passes for ehcache but exploits a number of memory leaks in JCS. JCS will give an OutOfMemory error with a default 64M in 10 seconds.
LinkedHashMap The MemoryStore for JDK1.4 and JDK 5 it is backed by an extended LinkedHashMap. This provides a combined linked list and a hash map, and is ideally suited for caching. Using this standard Java class simplifies the implementation of the memory cache. It directly supports obtaining the least recently used element.
For JDK1.2 and JDK1.3, the LRUMap from Apache Commons is used. It provides similar features to LinkedHashMap.
The implementation is determined dynamically at runtime. LinkedHashMap is preferred if found in the classpath.
The memory store, being all in memory, is the fastest caching option.
All caches specify their maximum in-memory size, in terms of the number of elements, at configuration time.
When an element is added to a cache and it goes beyond its maximum memory size, an existing element is either deleted, if overflowToDisk is false, or evaluated for spooling to disk, if overflowToDisk is true. In the latter case, a check for expiry is carried out. If it is expired it is deleted; if not it is spooled. The eviction of an item from the memory store is based on the MemoryStoreEvictionPolicy setting specified in the configuration file.
memoryStoreEvictionPolicy is an optional attribute in ehcache.xml introduced since 1.2. Legal values are LRU (default), LFU and FIFO.
LRU, LFU and FIFO eviction policies are supported. LRU is the default, consistent with all earlier releases of ehcache.
The eldest element, is the Least Recently Used (LRU). The last used timestamp is updated when an element is put into the cache or an element is retrieved from the cache with a get call.
For each get call on the element the number of hits is updated. When a put call is made for a new element (and assuming that the max limit is reached for the memory store) the element with least number of hits, the Less Frequently Used element, is evicted.
Elements are evicted in the same order as they come in. When a put call is made for a new element (and assuming that the max limit is reached for the memory store) the element that was placed first (First-In) in the store is the candidate for eviction (First-Out).
For all the eviction policies there are also putQuiet and getQuiet methods which do not update the last used timestamp.
When there is a get or a getQuiet on an element, it is checked for expiry. If expired, it is removed and null is returned.
Note that at any point in time there will usually be some expired elements in the cache. Memory sizing of an application must always take into account the maximum size of each cache. There is a convenience method which can provide an estimate of the size in bytes of the MemoryStore. See calculateInMemorySize(). It returns the serialized size of the cache. Do not use this method in production. It is very slow. It is only meant to provide a rough estimate.
The alternative would have been to have an expiry thread. This is a trade-off between lower memory use and short locking periods and cpu utilisation. The design is in favour of the latter. For those concerned with memory use, simply reduce the maxElementsInMemory.
The DiskStore provides a disk spooling facility.
Only Elements which are Serializable can be placed in the DiskStore. Any non serializable Elements which attempt to overflow to the DiskStore will be removed instead, and a WARNING level log message emitted.
It has the following characteristics:
The disk store creates one file per cache called "cache name.data".
If the DiskStore is configured to be persistent, a "cache name.index" file is also created.
Files are created in the directory specified by the diskStore configuration element. The default configuration is "java.io.tmpdir", which causes files to be created in the system's temporary directory.
Following is a list of Java system properties which are supported as values for diskStore:
Apart from these, any directory can be specified using syntax appropriate to the operating system. e.g. for Unix "/home/application/cache".
One thread per cache is used to remove expired elements. The optional attribute diskExpiryThreadIntervalSeconds sets the interval between runs of the expiry thread. Warning: setting this to a low value is not recommended. It can cause excessive DiskStore locking and high cpu utilisation. The default value is 120 seconds.
If the maxElementsOnDisk attribute is set, elements will be evicted from the DiskStore when it exceeds that amount. The LFU algorithm is used for these evictions. It is not configurable to use another algorithm.
Only Serializable objects can be stored in a DiskStore. A NotSerializableException will be thrown if the object is not serializable.
DiskStores are thread safe.
DiskStore persistence is controlled by the diskPersistent configuration element. If false or omitted, DiskStores will not persist between CacheManager restarts. The data file for each cache will be deleted, if it exists, both on shutdown and startup. No data from a previous instance CacheManager is available.
If diskPersistent is true, the data file, and an index file, are saved. Cache Elements are available to a new CacheManager. This CacheManager may be in the same VM instance, or a new one.
The data file is updated continuously during operation of the Disk Store. New elements are spooled to disk, and deleted when expired. The index file is only written when dispose is called on the DiskStore. This happens when the CacheManager is shut down, a Cache is disposed, or the VM is being shut down. It is recommended that the CacheManager shutdown() method be used. See Virtual Machine Shutdown Considerations for guidance on how to safely shut the Virtual Machine down.
When a DiskStore is persisted, the following steps take place:
On startup the following steps take place:
These actions favour safety over persistence. Ehcache is a cache, not a database. If a file gets dirty, all data is deleted. Once started there is further checking for corruption. When a get is done, if the Element cannot be successfully derserialized, it is deleted, and null is returned. These measures prevent corrupt and inconsistent data being returned.
Expiring an element frees its space on the file. This space is available for reuse by new elements. The element is also removed from the in-memory index of elements.
Spool requests are placed in-memory and then asynchronously written to disk. There is one thread per cache. An in-memory index of elements on disk is maintained to quickly resolve whether a key exists on disk, and if so to seek it and read it.
Writes to and