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. iOS 10.3下使用Fiddler抓取HTTPS请求

    最近使用Fiddler抓取手机上的HTTPS请求时,遇到一个问题.设置完之后,访问HTTPS的页面,却得到一个错误 网络出错,轻触屏幕重新加载:-1202 (如下图所示)   我印象中,之前都好好的, ...

  2. Linux下 $(cd `dirname $0`;pwd)

    在命令行状态下单纯执行 $ cd `dirname $0` 是毫无意义的.因为他返回当前路径的".".这个命令写在脚本文件里才有作用,他返回这个脚本文件放置的目录,并可以根据这个目 ...

  3. JavaScript 空间分析库——JSTS和Turf【转】

    https://blog.csdn.net/neimeng0/article/details/80363468 前言 项目中有管线的空间拓扑关系查询需求,在npm中检索到JSTS和Turf两个Java ...

  4. python新建txt文件,并逐行写入数据

    #coding=utf-8 txtName = "codingWord.txt"f=file(txtName, "a+")for i in range(1,10 ...

  5. 018-Go将磁盘目录实现简单的静态Web服务

    package main import( "net/http" ) func main(){ http.Handle("/", http.FileServer( ...

  6. VTK拾取网格模型上的可见点

    消隐与Z-Buffer 使用缓冲器记录物体表面在屏幕上投影所覆盖范围内的全部像素的深度值,依次访问屏幕范围内物体表面所覆盖的每一像素,用深度小(深度用z值表示,z值小表示离视点近)的像素点颜色替代深度 ...

  7. Swift Defer 延迟调用

    1.Defer 在一些语言中,有 try/finally 这样的控制语句,比如 Java.这种语句可以让我们在 finally 代码块中执行必须要执行的代码,不管之前怎样的兴风作浪.在 Swift 2 ...

  8. 查看修改添加环境变量的工具——Rapid Environment Editor

    工欲善其事,必先利其器! 特别是公司或者有其他限制的时候,更需要一个比较简单.实用.强大的工具了! 原来的公司都是小公司,给电脑安装系统.软件等都是自己直接上手,现在在一个大点的公司了,电脑运维有单独 ...

  9. Android 网络知识必知必会

    目录: 网络分层 TCP 和 UDP 区别 TCP 三次握手以及为什么需要三次握手 UDP 四次挥手以及为什么需要四次挥手 socket 开发相关 Http 是什么 Https 是什么以及和 HTTP ...

  10. vertx插件使用vertx-maven-plugin

    http://search.maven.org http://search.maven.org/#artifactdetails%7Cio.fabric8%7Cvertx-maven-plugin%7 ...