三津石智巳

👦🏻👦🏻👧🏻 Father of 3 | 🗺️ Service Reliability Engineering Manager at Rakuten Travel | 📚 Avid Reader | 👍 Wagashi | 👍 Caffe Latte | 👍 Owarai

【感想】Java Performance, 2nd Edition

5. An Introduction to Garbage Collection - Java Performance, 2nd Edition [Book]
metaspaceを勉強したい。

"Because the default size of metaspace is unlimited, an application (particularly in a 32-bit JVM) could run out of memory by filling up metaspace. The Native Memory Tracking (NMT) tools discussed in Chapter 8 can help diagnose that case. If metaspace is growing too big, you can set the value of MaxMetaspaceSize lower—but then the application will eventually get an OutOfMemoryError when the metaspace fills up. Figuring out why the class metadata is too large is the real remedy in that case."

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/-/9781492056102/ch05.html

metaspcae内のused/capacity/committed/reservedが異なることを理解していなければならない。
特に、APM等がmetaspaceを代表するメトリクスとしてusedだけを使用している場合には、metaspaceとnative memoryを見間違えやすいかもしれない。

なお、java - Understanding metaspace line in JVM heap printout - Stack Overflow
が非常に分かりやすい。こういう回答をStack Overflowでできるようになりたい。

"One reason to limit the size of the metaspace is to guard against a classloader leak: when the application server (or other program like an IDE) continually defines new classloaders and classes while maintaining references to the old classloaders. "

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/-/9781492056102/ch05.html

classloade leakを防ぐために(というか早期検知するために)XX:MaxMetaspaceSizeを設定するというのはなくはないのかもしれないが、むしろmetaspace監視をできるようになりたいところ。ちなみに、XX:MaxMetaspaceSizeをセットした場合はout of memory errorが起きる。

"However, be aware that the JVM will sometimes issue this error for things that have nothing to do with memory."

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/-/9781492056102/ch07.html

しかしながら、out of memory errorはmemoryが全く関係ないときにも発生したりするので注意が必要だ。

"The second case is trickier: it involves a classloader memory leak. This occurs most frequently in a server that loads classes dynamically. One such example is a Java EE application server."

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/-/9781492056102/ch07.html

metaspace out of memory errorの要因の一つにclassloader leakがある。

"We start with a discussion of the entire memory use of the JVM, with a goal of understanding how to monitor that usage for performance issues. Then we’ll discuss various ways to tune the JVM and operating system for optimal memory use."

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/-/9781492056102/ch08.html

結局のところheap/nonheapメモリのfootprintを知ることが必要になる。

"The total of native and heap memory used by the JVM yields the total footprint of an application."

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/-/9781492056102/ch08.html

native memoryとnonheapメモリの使い分けがいまいちわからない。metaspaceはnative memoryなのだろうか。

"This nonheap memory is native memory."

via Check out this quote from Java Performance, 2nd Edition - https://learning.oreilly.com/library/view/java-performance-2nd/9781492056102/ch08.html

この本の定義では上記理解であってそう。

linux - Java using much more memory than heap size (or size correctly Docker memory limit) - Stack Overflow
と思ったらもっと深かった。そしてまたapangin氏の回答である。この回答ではnonheapのことをoff-heapと呼んでいる。明確な定義があるわけではないが、Native Memory Tracking (NMT) で監視できないメモリがあるということを意識しておきたい。


memory footprintの解説についてはこのYouTubeの方が見ごたえがあった。

個人的には2-3%の性能劣化があったとしてもNative Memory Tracking (NMT) はproductionでonにしておくべきなのではという印象を持った。

話は変わってreflectionによるmemory leakの可能性について考えてみたい。

When using Java reflection, if the JVM uses a Java bytecode accessor on the class being reflected, it will use native memory. If there is frequent use of Java reflection, there can be a significant amount of native memory use.

https://www.ibm.com/support/pages/troubleshooting-native-memory-issues

可能性 1. sun/reflect/GeneratedMethodAccessorの数がsystem memoryに対して多すぎる。すなわちリフレクションを使いすぎている。たとえば、session scopeのbeanから

可能性 2. sun/reflect/GeneratedMethodAccessorGCされない。