JVM的主要划分为: 堆内存,虚拟机栈,方法区,程序计数器,本地方法栈

堆内存: 这部分区域是各个线程共享的,java的大部分对象都是储存在堆中。

1.堆在分配对象内存区域的时候可以分为两种,第一种叫做指针碰撞,这总方式在于内存区域是连续的,使用过的内存存在在一边,未使用的内存存放在另外一边,而中间是用指针来进行区分的,当我们需要创建一个新对象的时候,只需要将这个指针移动一个对象的长度即可,这种方式就相当于数据结构中的顺序存储。而第二种叫做闲置列表,这种方式不要求内存是连续的,需要维护一个列表,标记哪些部分是使用过的,那些部分是未使用过的,当我们创建新对象的时候,只需要将未使用的一块内存分配给对象即可,同时将这个信息记录到列表中去,这种方式相当于数据结构中的链式储存。

2.还需要考虑的一个问题就是因为创建对象是直接在内存中进行分配,可能会出现并发的情况,所以在创建对象的时候需要进行处理,主要的方式有采用CAS的方式或者是采用TLAB(Thread local Allocation Buffer 即为每一个线程预先分配一块区域,如果不够的话,在进行扩容),第二种方式可以采用JVM参数: -XX:-/+UseTLAB .

3.堆主要分为几个部分:年轻代和老年代。

年轻代 又分为Eden和两个survivor区,年轻代的大小可以通过-Xmnsize 进行分配,注意这里是不能大于总的堆大小的(Xms,Xmx)
我们还可以通过XX:SurvivorRatio=ratio 设置Eden区和一个s区的大小比例。对象的分配主要是在Eden区(如果没有开启TLAB),如果Eden区没有足够的空间的话,那么就会触发一次Minior GC(可以通过 -XX:+PrintGCDetails 打印GC信息),发生Minior GC的时候,对象就会被放入到s区,当s区的对象在多次的MiniorGC之后还存在的话,那么就直接进入了老年代,同时需要注意MiniorGC是分成频繁的。
    老年代 指的是那些在MiniorGC存活下来的对象(也就表示这些对象经常被使用,不会频繁的被清理),如果老年代内存不足的话,那么就会发生一次Full GC,Full GC是非常影响性能的,他会停止和他相关的工作,如果遇到很大的堆内存,停留的时间可能会很长,所以需要注意。

虚拟机栈: 虚拟机栈是线程隔离的,也就是说虚拟机栈中的东西其他线程是看不到的,主要存放的有局部变量表,操作数栈,动态链接和方法出。

局部变量表存放的有基本类型(short int long float double char byte boolean),对象的引用(包括数组的),其中long double 占用了两个局部变量空间(Slot 局部变量表的容量以变量槽(Slot)为最小单位,32位虚拟机中一个Slot可以存放一个32位以内的数据类型(boolean、byte、char、short、int、float、reference和returnAddress八种),注意局部变量表存放的是方法参数内部定义的变量。

操作数栈 是一个栈的形式,其中在方法内的计算都将压入栈(类似逆波兰)。

动态链接 表示的是对方法对常量池的引用。

方法出口  一个线程的栈是由多个栈帧组成的,一般我们在使用方法的时候都是一条调用链,也就说每一个方法就是对应一个栈帧(这也可以通过理解一般方法调用链都是先执行最后调用的方法【毕竟这是一个栈嘛】)

方法区:在Hotspot中为被称为是永久带(在JDK8已经被Metaspaces替代了),其中需要存放的是类信息,常量,静态变量以及即时编译器变异后的代码。

程序计数器:因为Java是多线程模型,所以多个线程会经常切换,那么我们就需要在切换的时候保存当前的执行位置和一些必须的变量,那么在切换回来的时候就可以继续的执行了。

本地方法栈:和虚拟机栈相似,不过这些方法不是在JVM中执行的,所以也不会占用堆内存,但是需要注意的是,需要保证操作系统留有足够的空间在支持本地方法的执行。

下面是一个理解中的JVM:

JVM常用参数

 * -XmsSize(最小堆内存)
* -XmxSize(最大堆内存)
* -XmnSize(分配给年轻代)
* -XX:+PrintGCDetails 输出详细GC日志
* -XX:SurvivorRatio=ratio Eden区和survivor区的比例
* -XX:-UseTLAB 是否使用本地线程分配缓冲
* -XX:+HeapDumpOnOutOfMemoryError(在出现异常的情况下 将内存快照dump出来)
* -XssSize 栈大小
* -XX:MaxPermSize 方法区的最大值(JDK<=1.7 .8将方法区移去,增加了metaspaces)
* -XX:PermSize 方法区的大小

Java中出现OutOfMemeoryError的情况

出现这种情况可以分为两种,分别是内存溢出和内存泄露

内存溢出  出行内存溢出的原因在于内存没用分配好,需要根据具体情况进行设置,其中可能是堆内存不足,也可能是系统内存不足(本地方法栈或者是虚拟机栈不够),或者是线程数太多(线程数<( 操作系统可用内存-堆内存)/栈大小)

内存泄露: 内存泄露可能是人为的一些操作导致的,对于没有使用的对象却一直保持了到Root间的可达(可达的意思是说一个对象可以和Root之间间接后者直接有引用关系,而Root一般为:虚拟机栈中的栈帧中的局部变量表的变量,方法区静态属性引用的对象,方法区中的常量引用的对象,本地方法中引用的变量)

在生产环境中强烈的要求设置HeapDumpOnOutOfMemoryError  这样在出现问题之后能够把内存快照给dump出来(因为这些问题很难重现)。便于使用工具进行分析,进而进行解决。

参考:

1.深入理解Java虚拟机 第二章

2,栈帧、局部变量表、操作数栈 http://wangwengcn.iteye.com/blog/1622195

JVM的内存划分以及常用参数的更多相关文章

  1. JDK8中JVM堆内存划分

    一:JVM中内存 JVM中内存通常划分为两个部分,分别为堆内存与栈内存,栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址. JVM全部的对象信息都 存放在堆内存中.相比 ...

  2. JVM堆内存相关的启动参数:年轻代、老年代和永久代的内存分配

    如果想观察JVM进程占用的堆内存,可以通过命令工具jmap或者可视化工具jvisualvm.exe.JVM这些启动参数都拥有默认值,如果想了解JVM的内存分配策略,最好手动设置这些启动参数.再通过JD ...

  3. Weblogic内存溢出及常用参数配置

        http://www.360doc.com/content/14/0306/14/16134804_358216319.shtml 一.WebLogic内存溢出 最近访问量门户访问量突然增大, ...

  4. (适合入门)JVM堆内存相关的启动参数:年轻一代、岁和永久代内存分配

    假设你要观察JVM进程消耗的堆内存,通过命令工具jmap或可视化工具jvisualvm.exe.JVM这些参数的默认启动值.假设你想知道JVM内存分配策略,最开始手动设置这些参数.通过JDK统计结果, ...

  5. Java学习笔记9---类静态成员变量的存储位置及JVM的内存划分

    笔记8提到了类静态成员变量的访问方式,但静态成员变量存储在哪里呢?在网上查阅不少资料,发现好多内容都是过时的了,其中主流观点是静态成员变量存放在方法区.JDK8之前,静态成员变量确实存放在方法区:但J ...

  6. JVM的内存划分

    1.栈内存:栈内存主要是用来运行函数的,在函数中定义的所有变量,都会在这个内存开辟空间. 在栈内存中定义的变量,不初始化,是不能直接使用的. 注意:所有的函数都必须在栈内存中运行. 而jvm只会运行处 ...

  7. JVM Java 内存区域透彻分析(转)

    出处:  Java 内存区域透彻分析  Java8内存模型—永久代(PermGen)和元空间(Metaspace) 这篇文章主要介绍Java内存区域,也是作为Java虚拟机的一些最基本的知识,理解了这 ...

  8. jvm的内存分配总结

    最近看了周志明版本的<深入理解Java虚拟机>第一版和第二版,写的很好,收获很多,此处总结一下.   jvm中内存划分:   如上图,一共分为五块,其中: 线程共享区域为: 1.java堆 ...

  9. 第1篇--基于jdk7和jdk8分析 JVM的内存区域

     基于jdk7和jdk8分析 JVM的内存区域 目录前言1.什么是JVM2.JRE/JDK/JVM是什么关系3.JVM执行程序的过程4. JVM的生命周期5.JVM垃圾回收一.运行时数据区的组成1.程 ...

随机推荐

  1. vue_axios请求封装、异常拦截统一处理

    1.前端网络请求封装.异常统一处理 vue中采用axios处理网络请求,避免请求接口重复代码,以及各种网络情况造成的异常情况的判断,采用axios请求封装和异常拦截操作: axios 请求封装 // ...

  2. 基于Socket网络编程

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a2011480169/article/details/73602708 博客核心内容: 1.Sock ...

  3. Linux系统中安装使用百度云网盘

    百度云没有Linux客户端,于是有大神用Go语言写出来一个叫BaiduPCS-Go的命令行盘客户端,可以通过终端操作百度云盘,在Linux上实现上传下载.但是因为是命令行版本的,对没有命令行使用基础的 ...

  4. 微信出现BUG,发送“ 两位数字+15个句号 ”,双方系统会卡崩……

    刚刚,有网友反映称,微信出现了新的bug.例如,在微信中发“两位数字+15个句号”(另一说法是任意数字,任意15个标点符号),如果有华为手机或者安卓手机收到,就会卡死. 用安卓手机的朋友可以试一下,不 ...

  5. Java 终于有 Lambda 表达式啦~Java 8 语言变化——Lambda 表达式和接口类更改【转载】

    原文地址 en cn 下载 Demo Java™ 8 包含一些重要的新的语言功能,为您提供了构建程序的更简单方式.Lambda 表达式 为内联代码块定义一种新语法,其灵活性与匿名内部类一样,但样板文件 ...

  6. C# 怎么让winform程序中的输入文本框保留上次的输入

    选中TextBox控件,在属性窗格中找到(ApplicationSettings),然后设置它. 绑定配置文件 private Settings settings = new Settings(); ...

  7. Tomcat 七 HTTP 连接器

    摘要 本文尝试翻译Tomcat官方文档Apache Tomcat 7连接器,不足之处敬请指正.该文先介绍了Tomcat7 HTTP连接器的属性,包括:公共属性.标准实现.Java TCP套接字属性.B ...

  8. JVM内存模型、指令重排、内存屏障概念解析(转载)

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  9. DataTables 全局设置中文语言

    参考来源:https://blog.csdn.net/qq_22690445/article/details/79682311 $.fn.dataTable.defaults.oLanguage = ...

  10. java 路径分隔符自动适配

    linux文件路径分隔符为 /  ,windows的文件路径分隔符为  \   ,在开发项目过程中不确定用户使用何种操作系统,就需要自动适配路径. 目前已知java提供两种方法获取文件路径分割符: F ...