Understanding Java Memory Model-理解java内存模型(JVM)
from https://medium.com/platform-engineer/understanding-java-memory-model-1d0863f6d973
Understanding Java Memory Model is an essential learning for serious Java developers who develop, deploy, monitor, test, and tune performance of a Java application. In this blog post, we are going to discuss on Java memory model and how each part of JVM memory contributes to run our programs.
First of all, check whether you understand the following diagram of JVM architecture. If you are not familiar with it, I highly suggest you to skim through my previous post (“Java Ecosystem (Part 1): Understanding JVM Architecture“) and refresh your knowledge.
JVM Architecture
JVM Memory Model
You must have used some of the following JVM memory configurations when running resource-intensive Java programs.
- -XmsSetting — initial Heap size
- -XmxSetting — maximum Heap size
- -XX:NewSizeSetting — new generation heap size
- -XX:MaxNewSizeSetting — maximum New generation heap size
- -XX:MaxPermGenSetting — maximum size of Permanent generation
- -XX:SurvivorRatioSetting — new heap size ratios (e.g. if Young Gen size is 10m and memory switch is –XX:SurvivorRatio=2, then 5m will be reserved for Eden space and 2.5m each for both Survivor spaces, default value = 8)
- -XX:NewRatio — providing ratio of Old/New Gen sizes (default value = 2)
But have you ever wondered how your JVM resides on memory? Let me show it. Just like any other software, JVM consumes the available space on host OS memory.
Host OS Memory and JVM
However, inside JVM, there exist separate memory spaces (Heap, Non-Heap, Cache) in order to store runtime data and compiled code.
1) Heap Memory
- Heap is divided into 2 parts — Young Generation and Old Generation
- Heap is allocated when JVM starts up (Initial size: -Xms)
- Heap size increases/decreases while the application is running
- Maximum size: -Xmx
JVM Heap Memory
1.1) Young Generation
- This is reserved for containing newly-allocated objects
- Young Gen includes three parts — Eden Memory and two Survivor Memory spaces (S0, S1)
- Most of the newly-created objects goes Eden space.
- When Eden space is filled with objects, Minor GC (a.k.a. Young Collection) is performed and all the survivor objects are moved to one of the survivor spaces.
- Minor GC also checks the survivor objects and move them to the other survivor space. So at a time, one of the survivor space is always empty.
- Objects that are survived after many cycles of GC, are moved to the Old generation memory space. Usually it’s done by setting a threshold for the age of the young generation objects before they become eligible to promote to Old generation.
1.2) Old Generation
- This is reserved for containing long lived objects that could survive after many rounds of Minor GC
- When Old Gen space is full, Major GC (a.k.a. Old Collection) is performed (usually takes longer time)
2) Non-Heap Memory
- This includes Permanent Generation (Replaced by Metaspace since Java 8)
- Perm Gen stores per-class structures such as runtime constant pool, field and method data, and the code for methods and constructors, as well as interned Strings
- Its size can be changed using -XX:PermSize and -XX:MaxPermSize
JVM Non-Heap & Cache Memory
3) Cache Memory
- This includes Code Cache
- Stores compiled code (i.e. native code) generated by JIT compiler, JVM internal structures, loaded profiler agent code and data, etc.
- When Code Cache exceeds a threshold, it gets flushed (and objects are not relocated by the GC).
Stack vs. Heap
So far I did not mention anything about Java Stack memory because I wanted to highlight its difference separately. First, take a look at the below image and check whether you know what’s happening here. I have already discussed on JVM Stack in my previous post.
JVM Stack, Non-Heap, and Heap (Image: jamesdbloom.com)
Anyway long story short, Java Stack memory is used for execution of a thread and it contains method specific values and references to other objects in Heap. Let’s put both Stack and Heap into a table and see their differences.

Here’s a nice example (from baeldung.com) on how Stack and Heap contribute to execute a simple program (Check the stack order with the code).
class Person {
int pid;
String name;// constructor, setters/getters
}public class Driver {
public static void main(String[] args) {
int id = 23;
String pName = "Jon";
Person p = null;
p = new Person(id, pName);
}
}
Stack Memory & Heap Space in Java (Image: baeldung.com)
Modifications
The above Java memory model is the most commonly-discussed implementation. However the latest JVM versions have different modifications such as introducing the following new memory spaces.
- Keep Area — a new memory space in Young Generation to contain the most recently allocated objects. No GC is performed until the next Young Generation. This area prevents objects from being promoted just because they were allocated right before a young collection is started.
- Metaspace — Since Java 8, Permanent Generation is replaced by Metaspace. It can auto increase its size (up to what the underlying OS provides) even though Perm Gen always has a fixed maximum size. As long as the classloader is alive, the metadata remains alive in the Metaspace and can’t be freed.
NOTE: You are always advised to go through the vendor docs to find out what works for your JVM version.
Memory Related Issues
When there is a critical memory issue, the JVM gets crashed and throws an error indication in your program output like below.
- java.lang.StackOverFlowError — indicates that Stack Memory is full
- java.lang.OutOfMemoryError: Java heap space — indicates that Heap Memory is full
- java.lang.OutOfMemoryError: GC Overhead limit exceeded — indicates that GC has reached its overhead limit
- java.lang.OutOfMemoryError: Permgen space — indicates that Permanent Generation space is full
- java.lang.OutOfMemoryError: Metaspace — indicates that Metaspace is full (since Java 8)
- java.lang.OutOfMemoryError: Unable to create new native thread— indicates that JVM native code can no longer create a new native thread from the underlying operating system because so many threads have been already created and they consume all the available memory for the JVM
- java.lang.OutOfMemoryError: request size bytes for reason — indicates that swap memory space is fully consumed by application
- java.lang.OutOfMemoryError: Requested array size exceeds VM limit– indicates that our application uses an array size more than the allowed size for the underlying platform
However, what you have to thoroughly understand is that these outputs can only indicate the impact that the JVM had, not the actual error. The actual error and its root cause conditions can occur somewhere in your code (e.g. memory leak, GC issue, synchronization problem), resource allocation, or maybe even hardware setting. Therefore, I can’t advise you to simply increase the affected resource size to solve the problem. Maybe you will need to monitor resource usage, profile each category, go through heap dumps, check and debug/optimize your code etc. And if none of your efforts seems to work and/or your context knowledge indicates that you need more resources, go for it.
What’s Next
During my undergraduate research on JVM performance aspects, we found several approaches used by the industry to minimize the impact of performance faults like memory errors. Let’s discuss about Java Performance Management in-depth very soon. In the meantime, read the next blog post of this series in which I explain how Java Garbage Collection really worksunder the hood. Stay excited with this blog for more exciting posts!
Be sure to follow me on Twitter @ashen_wgt and send me your feedback, comment any questions you have, let me know your suggestions and I’ll surely check it out/retweet! You can also share this post with your friends and check my other articles on PlatformEngineer.com
References
- JVM Internals — http://blog.jamesdbloom.com/JVMInternals.html
- Stack Memory and Heap Space in Java — https://www.baeldung.com/java-stack-heap
- Java (JVM) Memory Model — Memory Management in Java — https://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java
- Java Memory Management for Java Virtual Machine (JVM) — https://betsol.com/2017/06/java-memory-management-for-java-virtual-machine-jvm/
Understanding Java Memory Model-理解java内存模型(JVM)的更多相关文章
- JAVA内存模型(Java Memory Model ,JMM)
http://blog.csdn.net/hxpjava1/article/details/55189077 JVM有主内存(Main Memory)和工作内存(Working Memory),主内存 ...
- 并发研究之Java内存模型(Java Memory Model)
Java内存模型JMM java内存模型定义 上一遍文章我们讲到了CPU缓存一致性以及内存屏障问题.那么Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬 ...
- java内存模型(Java Memory Model)
内容导航: Java内存模型 硬件存储体系结构 Java内存模型和硬件存储体系之间的桥梁: 共享对象的可见性 竞争条件 Java内存模型规定了JVM怎样与计算机存储系统(RAM)协调工作.JVM是一个 ...
- java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解
一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工 ...
- java 深入理解jvm内存模型 jvm学习笔记
jvm内存模型 这是java堆和方法区内存模型 参考:https://www.cnblogs.com/honey01/p/9475726.html Java 中的堆也是 GC 收集垃圾的主要区域.GC ...
- 当我们在谈论JMM(Java memory model)的时候,我们在谈论些什么
前面几篇中,我们谈论了synchronized.final以及voilate的用法和底层实现,都绕不开一个话题-Java内存模型(java memory model,简称JMM).Java内存模型是保 ...
- 死磕 java同步系列之JMM(Java Memory Model)
简介 Java内存模型是在硬件内存模型上的更高层的抽象,它屏蔽了各种硬件和操作系统访问的差异性,保证了Java程序在各种平台下对内存的访问都能达到一致的效果. 硬件内存模型 在正式讲解Java的内存模 ...
- Java原子性、可见性、内存模型
原子性: 原子性就是指该操作是不可再分的.不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作.简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性.比如 a = ...
- java提高篇-----理解java的三大特性之封装
在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...
随机推荐
- 使用VSCode创建简单的Razor Webapp--2.添加模型
1.新建Models文件夹,并新建Movie.cs文件 using System; using System.ComponentModel.DataAnnotations; namespace Raz ...
- os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error='Cannot allocate memory' (errno=12)
centos 安装 elasticsearch的时候 因为 elasticsearch默认 需要 2G内存导致的镜像不能运行 解决方案 修改配置文件 find / -name jvm.options ...
- (转)java 虚拟机内存划分
深入理解java虚拟机(一):java内存区域(内存结构划分)深入理解java虚拟机(二):java内存溢出实战 深入理解java虚拟机(三):String.intern()-字符串常量池深入理解j ...
- nice-validator判断表单是否验证通过
$("#formSurvery").isValid(function(is){ if(is){ alert("通过!") } } 如果is为false则表示不通 ...
- MapReduce异常:java.lang.ClassCastException: interface javax.xml.soap.Text
MapReduce异常:java.lang.ClassCastException: interface javax.xml.soap.Text java.lang.ClassCastException ...
- 4-初识Django Admin
初识Django Admin Django Admin是Django为我们提供的网站后台管理应用,通常网站,个人博客,CMS等都会有个后台管理界面,这个界面只有管理员权限的用户才能进入管理网站内容.管 ...
- Mysql部分存储引擎介绍
Mysql存储引擎 什么是存储引擎 mysql中建立的库 --> 文件夹 库中建立的表 --> 文件 现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制: ...
- Qt程序异常结束,The process was ended forcefully....
我用的Qt版本是5.9.6,运行了好几次程序都妥妥当当的,然后就被安排上了...出现如下错误: 也是刚入手Qt不久,出现这样的错误我以为是代码的问题,然后撤销一些代码发现还是这样的错,索性就关闭Qt然 ...
- vue+muse-ui
1.可以很好的配合vue2.0开发 2.安装: npm install muse-ui --save 3.引入: 在main.js中加入 import Vue from 'vue' import M ...
- 训练20191005 2017-2018 ACM-ICPC Asia East Continent League Final
A 签到 M 签到 K 读懂后签到 L 博弈论 [引理]出现SXXS结构时后手必胜. 很容易发现n为奇数时后手不可能胜利,n为偶数时先手不可能胜利.n≤6时一定平局,n≥7时先手有可能胜利,n≥16时 ...