JVM内存结构和Java内存模型

一、JVM
首先看一张JVM结构图(某度找的)
程序计数器:一块较小的内存空间 , 是当前线程所执行的字节码的行号指示器 。 此区域是唯一一个不会产生OOM的内存区域 。
Java虚拟机栈:每个方法在执行的时候都会创建一个栈帧 , 用于存放局部变量表、操作数栈、动态链接、方法出口等信息 。 可能会发生StackOverflowError或者OOM 。
(1)当一直调用的时候(也就是栈的深度超过了虚拟机所允许的深度) , 就是跑出此异常 。
本地虚拟机栈:类似于Java虚拟机栈 , 不同的是java虚拟机栈执行的java方法 , 而本地虚拟机栈执行的Native方法(底层用C++所写) 。
方法区:存放已被主要用于存放类的信息 , 常量、静态变量、即时编译器编译后的代码等 , 另外运行时常量池也在这里 。 可能会出现OOM 。 (java8之后JVM就将方法区改成元空间 , 并与堆进行了合并)
(1)设置元空间大小 , 模拟元空间内存溢出
(1)设置堆大小 , 模拟堆内存溢出
(1)-Xms10m:相当于-XX:InitialHeapSize=10m , 最小堆内存
(2)-Xmx10m:相当于-XX:MaxHeapSize=10m , 最大堆内存
(3)-XX:MetaspaceSize:最小元空间大小 , 用法是-XX:MetaspaceSize=10m
(4)-XX:MaxMetaspaceSize:最大元空间大小
(5)-Xss1024k:单个线程栈的大小 。
(5)-Xmn1G:配置年轻代大小
(6)-XX:+PrintGCDetails:开启GC收集日志
(7)-XX:+PrintCommandLineFlags:输出自动优化参数
(8)-XX:UseSerialGC:使用串行垃圾收集器
如何在程序运行的时候查看JVM参数?
(1)先用jps-l获取进程id
(1)JMM本身是一种抽象的概念 , 描述的是一组规范 , 定义了变量的访问方式 。
(2)关于同步的规定:
1.线程解锁前 , 必须将同步变量刷新到主内存中
2.线程获取锁之后 , 必须将同步变量刷新到工作内存中
3.加锁和解锁是同一把锁 。
(3)由于JVM运行程序的主体是线程 , 而每个线程创建的时候都会有一个工作内存(栈) , 工作内存是线程的私有数据区域 , 而java内存模型中规定所有变量都存储在主内存(线程共享区域) , 但线程对变量的操作必须是在工作内存中完成 , 首先要把变量从主内存中拷贝到工作内存中 , 再对变量进行操作 , 操作完成再将变量写回到主内存中 。 不能直接操作主内存中的变量 。
【JVM内存结构和Java内存模型】(4)可见性 , 原子性(不可分割 , 例如某个线程正在做某个业务的时候 , 中间不可以被加塞 。 需要整体完整 , 要么同时成功 , 要么同时失败 。 ) , 有序性 。


    推荐阅读