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. layui table 超出自动换行

    个人博客 地址:http://www.wenhaofan.com/article/20181120180507 layui 的table的的cell默认是超出hidden的,如果希望超出长度自动换行便 ...

  2. 面试官所问的--Token认证

    写这一篇文章的来源是因为某一天的我被面试官提问:让你设计一个登录页面,你会如何设计? 我当时的脑子只有??? 不就是提交账号.密码给后台就搞定了呢? 不可能那么简单,我弱弱的想,难道要对密码加密?? ...

  3. 获取 Android APP 版本信息工具类(转载)

    获取 Android APP 版本信息工具类 获取手机APP版本信息工具类 1.获取版本名称 2.获取版本号 3.获取App的名称 package com.mingyue.nanshuibeidiao ...

  4. oracle sqlplus链接和sid

    1.链接 ( 1.sqlplus /nolog 2.conn sys/sys@172.16.17.36/orcl as sysdba ) 2.sid   数据库名称 ----如:orcl 1.监听程序 ...

  5. C语言循环语句工程用法

    -循环语句分析 循环语句的基本工作方式 - 通过条件表达式判断是否执行循环体 - 条件表达式循环if语句表达式的原则 do.while.for的区别 - do语句先执行后判断,循环体至少循环一次 - ...

  6. TWF

    design seq1_b3 sta_label 0.0-1.0 0.0-1.0 1e-9 # clocks# clockID clock_name period rise_edge fall_edg ...

  7. MYSQL获取表空间大小

    SELECT table_name AS "Table", round(((data_length + index_length) / 1024 / 1024), 2) as si ...

  8. 常见的sql语句练习

    一. 1.新建表 test id varchar2(20)name varchar2(20)addr varchar2(50)score number create table test(id var ...

  9. goahead 流程

    原文:https://blog.csdn.net/qq_32419007/article/details/80756643 1.全局变量 Web服务器的根目录 static char_t        ...

  10. .net core 2.2 使用imagemagick 将pdf转化为png

    工作需要将PDF文件每一页拆分为一个一个的png文件 测试环境:mac,visual studio for mac 2019 nuget:magick.net-Q16-AnyCPU 不能直接支持PDF ...