javahibernateehcacheehcache-3

Illegal reflective access warning for Ehcache when heap cache size is configured in MB


I am using Ehcache as the query cache for hibernate, and following is my Ehcache config.

<cache alias="default-query-results-region">
    <key-type>org.hibernate.cache.spi.QueryKey</key-type>
    <value-type>java.lang.Object</value-type>
    <expiry>
        <ttl unit="seconds">30</ttl>
    </expiry>
    <resources>
        <heap unit="MB">1</heap>
        <offheap unit="MB">2</offheap>
    </resources>
</cache>

I get following warning logged to the console when I execute my application.

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.ehcache.sizeof.ObjectGraphWalker (file:/C:/Users/<my_username>/.m2/repository/org/ehcache/ehcache/3.9.4/ehcache-3.9.4.jar) to field java.util.ArrayList.elementData
WARNING: Please consider reporting this to the maintainers of org.ehcache.sizeof.ObjectGraphWalker
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

But I don't get a warning if I specify the heap unit as entries.

<heap unit="entries">2</heap>

Below is the Ehcache version I am using.

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.9.4</version>
</dependency>

Below is from my hibernate config, where I have specified Ehcache as the cache provider.

<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.jcache.JCacheRegionFactory</property>
<property name="hibernate.javax.cache.provider">org.ehcache.jsr107.EhcacheCachingProvider</property>
<property name="hibernate.javax.cache.uri">ehcache.xml</property>

I am using OpenJDK 11.

What is the reason for this warning? Is there any way I can fix it?


Solution

  • If you constraint the cache by physical size i.e. MB, EHCache somehow has to probe all data structures to determine their actual size in bytes. To do this, it has to "break into" all classes reflectively to determine the size. You can use the following java command line flag to allow EHCache (but unfortunately also all other code) to do this: --add-opens=java.base/java.util=ALL-UNNAMED

    Note though that you might need to open other packages of the java.base modules as well depending on what kind of data structures you are using in your cache entries. A particular "security issue" that comes with this solution is that any other code your run can now do all sorts of things as well which Java 9 started to encapsulate to increase security. To restrict this "permission" only to EHCache, you would have to run in module mode though which I am not sure is what you want to do.

    Overall I suggest you to simply not use a heap configuration with a physical size. Use just offheap or the entries configuration based on some average entry size assumption.