什么是 Reserve CodeCacheSize 和 InitialCodeCacheSize?

有人能解释一下什么是 JVM 选项 ReservedCodeCacheSizeInitialCodeCacheSize吗?特别是什么时候/为什么我想要改变它?我如何决定什么是正确的大小?

医生是这么说的:

- XX: Reserve CodeCacheSize = 32m Reserve code cache size (单位: 字节)-最大代码缓存大小。[ Solaris 64位、 amd64和-server x86:2048m; 在1.5.0 _ 06及更早版本中,Solaris 64位和64:1024m。]

109730 次浏览

ReservedCodeCacheSize (and InitialCodeCacheSize) is an option for the (just-in-time) compiler of the Java Hotspot VM. Basically it sets the maximum size for the compiler's code cache.

The cache can become full, which results in warnings like the following:

Java HotSpot(TM) 64-Bit Server VM warning: CodeCache is full. Compiler has been disabled.
Java HotSpot(TM) 64-Bit Server VM warning: Try increasing the code cache size using -XX:ReservedCodeCacheSize=
Code Cache  [0x000000010958f000, 0x000000010c52f000, 0x000000010c58f000)
total_blobs=15406 nmethods=14989 adapters=362 free_code_cache=835Kb largest_free_block=449792

It's much worse when followed by Java HotSpot(TM) Client VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated.

When to set this option?

  1. when having Hotspot compiler failures
  2. to reduce memory needed by the JVM (and hence risking JIT compiler failures)

Normally you'd not change this value. I think the default values are quite good balanced because this problems occur on very rare occasions only (in my experince).

@jeha answers everything I wanted to know from this question, apart from what value to set the parameters to. As I didn't write the code I was deploying I didn't have much visibility into the memory footprint it had.

However, you can use jconsole to attach to your running java process, and then use the 'Memory' tab to find out the Code Cache size. For completeness, the steps are (Linux VM environment, though I'm sure other environments are similar):

  1. Fire up jconsole on your machine
  2. Find the right process ID and attach jconsole to it (this will take a few moments)
  3. Navigate to the 'Memory' tab
  4. From the 'Chart:' drop-down list, select 'Memory Pool "Code Cache"'
  5. Again, this may take a few moments for the screen to refresh, and then you should see something like: jconsole code cache image

    As you can see, my code cache is using approx 49 MB. At this point I still had the default which the documentation (and @jeha) says is 48 MB. Certainly a great motivation for me to increase the setting!

    Ben.


    1024 MB by default probably was overdoing it, but 48 MB by default seems to be underdoing it...

A good learning experience from Indeed engineering team and challenges they faced when migrating to jdk 8.

http://engineering.indeedblog.com/blog/2016/09/job-search-web-app-java-8-migration/

Conclusion : Jdk 8 needs more code cache han JDK 7

The default codecache size for JRE 8 is about 250MB, about five times larger than the 48MB default for JRE 7. Our experience is that JRE 8 needs that extra codecache. We have switched about ten services to JRE 8 so far, and all of them use about four times more codecache than before.

from https://blogs.oracle.com/poonam/entry/why_do_i_get_message:

The following are two known problems in jdk7u4+ with respect to the CodeCache flushing:

  1. The compiler may not get restarted even after the CodeCache occupancy drops down to almost half after the emergency flushing.
  2. The emergency flushing may cause high CPU usage by the compiler threads leading to overall performance degradation.

This performance issue, and the problem of the compiler not getting re-enabled again has been addressed in JDK8. To workaround these in JDK7u4+, we can increase the code cache size using ReservedCodeCacheSize option by setting it to a value larger than the compiled-code footprint so that the CodeCache never becomes full. Another solution to this is to disable the CodeCache Flushing using -XX:-UseCodeCacheFlushing JVM option.

The above mentioned issues have been fixed in JDK8 and its updates.

So that information might be worth mentioning for systems running on JDK 6 (having code flushing disabled) and 7.