
-Xmn:500M,就是说年轻代大小是500M(包括一个Eden和两个Survivor)
-XX:SurvivorRatio=3,就是说Eden区与Survivor区的大小比值为3:1:1
-XX:MaxPermSize:64M,就是说设置持久代最大值为64M
-Xms:1G,就是说初始堆大小为1G
-Xmx:2G,就是说最大堆大小为2G
-XX:+UseConcMarkSweepGC,就是说使用使用CMS内存收集算法
题目中所问的Eden区的大小是指年轻代的大小,直接根据-Xmn:500M和-XX:SurvivorRatio=3可以直接计算得出
500M×(3/(3+1+1))
=500M×(3/5)
=500M×0.6
=300M
所以Eden区域的大小为300M
[堆](堆.md)
面试官 | JVM 为什么使用元空间替换了永久代?- 码上技术指导老师的文章 - 知乎
https://zhuanlan.zhihu.com/p/111809384
虚拟机运行时数据区:2 和 3
虚拟机外:堆外/直接内存 1和 4
## 1、关于类的:类信息、常量、静态变量(都存在线程安全的问题)
方法区规范内还包括一个运行时常量池的规范,运行时常量池又包括一个字符串常量池的规范

存的是c++中的一种数据结构 instanceKlass,其中有一个属性java_mirror,存在heap中,使得Klass可以暴露给java使用
JDK7以上版本,静态域存储于定义类型的Class对象中,Class对象如同堆中其他对象一样,存在于GC堆中。
## 2、关于对象的:堆的实现包括新生代和老年代

这是一个对象的内存图
## 3、关于线程的:栈的实现包括虚拟机栈、程序计数器、和本地方法栈
其中虚拟机栈的栈帧内又包括:"局部变量表"、"操作数栈"、"动态链接"以及"方法出口"四个部分。
操作数栈
局部变量表(八种基本数据类型、引用、返回值)
动态链接(主要服务一个方法需要调用其他方法的场景)

## 4、直接内存
1、读写成本小
通过Java 堆中的 DirectByteBuffer操作,避免java堆和native堆之间的来回复制,也就是nio New Input
传统的阻塞io,得开辟两份缓冲区,操作系统管的内存开辟一份,java自己管的内存也开辟一份
第二张是new io只有一份缓冲区(java和操作系统都可管)
在内存建一个buffer,输入靠InputStream read, 输出靠 OutputStream write
[Pic#ID/5ZM9#]
2、回收成本大
直接内存也会导致内存溢出问题:
1、不受JVM内存回收管理,不会释放direct memory的内存。因为直接内存是属于操作系统的,java的内存回收不能回收他,
2、如果要回收,需要主动调用Unsafe对象的freeMemory方法,Unsafe是Java底层的类,一般不建议使用。
3、直接内存释放是借助了java的虚引用机制,ByteBuffer的实现类内部,使用了Cleaner(虚引用)来监测ByteBuffer对象,一旦ByteBuffer对象被垃圾回收,那么就会由ReferenceHandler线程通过Cleaner的clean方法调用freeMemory来释放直接内存。
内存布局:方法区位置的变化
1.8前在全部在永久代中实现。1.8在元空间(本地内存)上实现,其中的字符串常量池被安排在了堆中
另外还有一个直接内存是nio用来当缓冲区的,效率比较高

threadlocal