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

Understanding Java Memory Model-理解java内存模型(JVM)的更多相关文章

  1. JAVA内存模型(Java Memory Model ,JMM)

    http://blog.csdn.net/hxpjava1/article/details/55189077 JVM有主内存(Main Memory)和工作内存(Working Memory),主内存 ...

  2. 并发研究之Java内存模型(Java Memory Model)

    Java内存模型JMM java内存模型定义 上一遍文章我们讲到了CPU缓存一致性以及内存屏障问题.那么Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬 ...

  3. java内存模型(Java Memory Model)

    内容导航: Java内存模型 硬件存储体系结构 Java内存模型和硬件存储体系之间的桥梁: 共享对象的可见性 竞争条件 Java内存模型规定了JVM怎样与计算机存储系统(RAM)协调工作.JVM是一个 ...

  4. java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解

    一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工 ...

  5. java 深入理解jvm内存模型 jvm学习笔记

    jvm内存模型 这是java堆和方法区内存模型 参考:https://www.cnblogs.com/honey01/p/9475726.html Java 中的堆也是 GC 收集垃圾的主要区域.GC ...

  6. 当我们在谈论JMM(Java memory model)的时候,我们在谈论些什么

    前面几篇中,我们谈论了synchronized.final以及voilate的用法和底层实现,都绕不开一个话题-Java内存模型(java memory model,简称JMM).Java内存模型是保 ...

  7. 死磕 java同步系列之JMM(Java Memory Model)

    简介 Java内存模型是在硬件内存模型上的更高层的抽象,它屏蔽了各种硬件和操作系统访问的差异性,保证了Java程序在各种平台下对内存的访问都能达到一致的效果. 硬件内存模型 在正式讲解Java的内存模 ...

  8. Java原子性、可见性、内存模型

    原子性: 原子性就是指该操作是不可再分的.不论是多核还是单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作.简而言之,在整个操作过程中不会被线程调度器中断的操作,都可认为是原子性.比如 a = ...

  9. java提高篇-----理解java的三大特性之封装

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

随机推荐

  1. 【C语言】猴子吃桃问题

    题目: 猴子第一天吃了若干个桃子,当即吃了一半,还不解馋,又多吃了一个: 第二天,吃剩下的桃子的一半,还不过瘾,又多吃了一个:以后每天都吃前一天剩下的一半多一个,到第10天想再吃时,只剩下一个桃子了. ...

  2. DataGrid 的DataSource重新加载数据

    DataGrid 的DataSource重新加载数据,若直接重新给DataSource赋值是没有效果的,若只是修改原有数据中的单个值,此方法有效,但是针对完全不一样的数据直接重新赋值的方式是无效的,此 ...

  3. 高效完成R代码

    为什么R有时候运行慢? 参考https://www.cnblogs.com/qiaoyihang/p/7779144.html 一.为什么R程序有时候会很慢? 1.计算性能的三个限制条件 cpu ra ...

  4. 理解JWT(JSON Web Token)认证

    理解JWT(JSON Web Token)认证 最近想做个小程序,需要用到授权认证流程.以前项目都是用的 OAuth2 认证,但是Sanic 使用OAuth2 不太方便,就想试一下 JWT 的认证方式 ...

  5. ORA-00904: "I_LEVEL": invalid identifier

    问题描述 ORA-00904: "I_LEVEL": invalid identifier 标示符无效

  6. 安全相关的Linux知识

    本文用于记录在安全中的Linux常用命令,基础命令可以移步去菜鸟教程(https://www.runoob.com/linux/linux-tutorial.html)学习 Linux重要的4个热键 ...

  7. java json转换工具类

    在java项目中,通常会用到json类型的转换,常常需要对 json字符串和对象进行相互转换. 在制作自定义的json转换类之前,先引入以下依赖 <!--json相关工具--><de ...

  8. codeforces 1282 E. The Cake Is a Lie (dfs+构造)

    链接:https://codeforces.com/contest/1282/problem/E 题意:给的是一张平面图,是一个n边形,每次可以切一刀,切出一个三角形,最终切成n-2个三角形.题目给出 ...

  9. 并查集-G - 食物链

    G - 食物链 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A.现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种 ...

  10. 三剑客-sed awk

     目录 1.sed 2.awk 1.sed //sed命令 #语法说明:命令 参数 条件+处理= (指令) 处理文件信息 字符流编辑工具(行编辑工具)==按照每行中的字符进行处理操作 ). 擅长对行进 ...