JVM内存结构解析

月初的时候我的网站到期了,不想再折腾从新建站了,之后仍是来第三方博客写文章吧,能够省去不少问题。以前写的文章也不是不少,备份懒得作了,从头开始吧。博文仅仅是用来记录和学习总结,若有错误之处请帮忙指正!程序员

今天想说说JVM内存结构的问题,说到JVM你们确定首先想到的是栈和堆。的确,这两块说是JVM内存结构最重要的部分也不为过。先来简单介绍一下吧,数组

内存结构按照私有和共享划分方式以下:数据结构

线程私有:栈区、本地方法栈、程序计数器学习

线程共享:堆区、方法区测试

其余不说了,重点说说栈和堆优化


 

栈:网站

栈的特色就是快。每一个线程对应一个栈,每一个栈含有1个或多个栈帧,栈帧用来存放方法的局部变量表、操做数栈、动态连接、returnAddress等信息,每运行一个方法就会建立一个栈帧,从方法运行到结束对应着栈帧在栈区里面入栈和出栈的过程。线程

局部变量表包含两类数据结构,一是八大基本类型,byte short int long float double char boolean; 第二类是reference类型,占用空间是4byte,不论是对象是大是小,操控它仅须要用一个4byte的变量便可,并且能够按需销毁,这足以体现栈堆分离的好处。指针

栈空间是能够重复利用的,遇到左括号入栈,遇到右括号出栈,咱们当系统进行递归调用时,系统会连续屡次执行入栈操做,直到最深处才执行出栈操做,这就可能致使栈空间不足,StackOverFlowError异常,所以遇到该异常通常不是对象太大致使的,可能是由于不正确递归或栈空间不足以容纳致使。在栈区还可能会遇到OOM异常,当线程过多时或分配空间太小时,若是没法申请到足够内存时,便会报OOM异常(栈区OOM异常的缘由暂不肯定也为碰见过,只是周志明JVM书中提到栈区OOM异常,上网也未查到)。JVM调优:经过-Xss来控制栈空间大小。对象


堆:

堆是JVM内存中最大的一块,是用来为对象和数组元素分配空间的地方,而对象的引用变量和数组引用都是在栈中存放的。“几乎全部的对象都在这里建立”,那么什么状况下对象不在堆中建立呢?随着JIT编译器的发展,在编译期间,若是JIT经逃逸分析后发现对象没有逃逸出方法,那么该对象坑会在栈上分配内存而不是堆,可是也不绝对。测试:为JVM分配足够空间,关闭逃逸分析,建立一百万个User对象,jmap命令发现堆中建立了一百万个对象,开启逃逸分析,发现堆中的对象变成了八万个,也就是说JIT编译器确实会将对象分配在栈里,但并不绝对。

使用逃逸分析,编译器能够针对分析结果作如下优化:

一、同步省略(锁消除优化):若是一个对象被发现只能被一个线程访问,那么能够不考虑该对象的同步;

二、栈上分配对象;若是一个对象在子程序中被分配,要是指向该对象的指针永远不会逃逸,对象可能会在栈中被分配,而不是在堆中;

三、分离对象或标量替换:有的对象可能不须要连续的内存结构,能够将该对象的部分或所有存储到CPU的寄存器中。

逃逸分析:-XX:+/-DoEscapeAnalysis

关于堆的分代和垃圾收集下次再讲。


顺带讲一下,参数传递的时候,Java是传值仍是传引用?这个问题相信每一个程序员都会思考过,也确定遇到过由此引起的问题。

要说明这个问题,首先要说明两点:一是不要和C语言类比,Java没有指针的概念;二是程序运行永远都是在栈中进行,于是参数传递时涉及到的只会是基本数据类型和引用类型,理论上来讲不会涉及到对象自己。而Java中没有指针的概念,所以Java能够说是传值调用,当参数是引用类型时传递的是引用变量的值;可是当进入被调用方法时,被传递的这个引用的值,被程序解释(或者查找)到堆中的对象,这个时候才对应到真正的对象,这个时候若是对其进行修改,修改的并非引用自己,而是对象的属性,因此对对象的修改会保持。程序参数传递时,被传递的值自己都是不能进行修改的,可是,若是这个值是一个引用,则能够修改这个引用背后的东西。

相关文章
相关标签/搜索