月初的时候个人网站到期了,不想再折腾重新建站了,以后还是来第三方博客写文章吧,可以省去很多问题。之前写的文章也不是很多,备份懒得做了,从头开始吧。博文仅仅是用来记录和学习总结,如有错误之处请帮忙指正!

今天想说说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编译器确实会将对象分配在栈里,但并不绝对。

使用逃逸分析,编译器可以针对分析结果做以下优化:

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

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

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

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

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


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

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

JVM内存结构解析的更多相关文章

  1. 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控

    如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...

  2. JVM内存结构,运行机制

    三月十号,白天出去有事情出去了一天,晚上刚到食堂就接到阿里电话, 紧张到不行,很多基础的问题都不知道从哪里说了orz: 其中关于JVM内存结构,运行机制,自己笔记里面有总结的,可当天还是一下子说不出来 ...

  3. JVM内存结构 JVM的类加载机制

    JVM内存结构: 1.java虚拟机栈:存放的是对象的引用(指针)和局部变量 2.程序计数器:每个线程都有一个程序计数器,跟踪代码运行到哪个位置了 3.堆:对象.数组 4.方法区:字节流(字节码文件) ...

  4. JVM入门——JVM内存结构

    一.java代码编译执行过程 1.源码编译:通过Java源码编译器将Java代码编译成JVM字节码(.class文件) 2.类加载:通过ClassLoader及其子类来完成JVM的类加载 3.类执行: ...

  5. JVM(七):JVM内存结构

    JVM(七):JVM内存结构 在前几节的文章我们多次讲到 Class 对象需要分配入 JVM 内存,并在 JVM 内存中执行 Java 代码,完成对象内存的分配.执行.回收等操作,因此,如今让我们来走 ...

  6. 万万没想到,JVM内存结构的面试题可以问的这么难?

    在我的博客中,之前有很多文章介绍过JVM内存结构,相信很多看多我文章的朋友对这部分知识都有一定的了解了. 那么,请大家尝试着回答一下以下问题: 1.JVM管理的内存结构是怎样的? 2.不同的虚拟机在实 ...

  7. Java 内存模型和 JVM 内存结构真不是一回事

    这两个概念估计有不少人会混淆,它们都可以说是 JVM 规范的一部分,但真不是一回事!它们描述和解决的是不同问题,简单来说, Java 内存模型,描述的是多线程允许的行为 JVM 内存结构,描述的是线程 ...

  8. JDK8的JVM内存结构,元空间替代永久代成为方法区及常量池的变化

    JVM的知识这里总结的很详细:https://github.com/doocs/jvm/blob/master/README.md,因此在本博客也不会再对其中的东西重复总结了. 现在很多文章关于JVM ...

  9. JVM内存结构划分

    JVM内存结构划分 JVM内存结构划分 数据区域划分 程序计数器 虚拟机栈 本地方法栈 堆 方法区 运行时常量池 StringTable 直接内存 创建新对象说明 对象的创建 对象的内存布局 对象头 ...

随机推荐

  1. 赵伟国辞去TCL集团董事等职位,紫光参与TCL定增浮盈已超7亿

    集微网消息,TCL 集团于8月9日晚间发布公告称,公司董事会于近日收到董事赵伟国先生的书面辞职报告,赵伟国先生因个人原因申请辞去公司董事及公司战略委员会委员职务.辞任后,赵伟国先生不再担任公司任何职务 ...

  2. passed into methods by value java专题

    java没有引用传递只有按值传递,没有引用传递只有按值传递,值传递.因为Primitive类型的值不能改变,所以method不能更改调用方传的primitive 值.因为method更改的是Primi ...

  3. C++杂记:运行时类型识别(RTTI)与动态类型转换原理

    运行时类型识别(RTTI)的引入有三个作用: 配合typeid操作符的实现: 实现异常处理中catch的匹配过程: 实现动态类型转换dynamic_cast. 1. typeid操作符的实现 1.1. ...

  4. WPF MVVM+EF增删改查 简单示例(二) 1对1 映射

    WPF MVVM+EF增删改查 简单示例(一)实现了对学生信息的管理. 现在需求发生变更,在录入学生资料的时候同时需要录入学生的图片信息,并且一名学生只能有一张图片资料.并可对学生的图片资料进行更新. ...

  5. nprogress.js 头部进度条使用方法

    nprogress.js 头部进度条 引入CSS\JS <link rel="stylesheet" type="text/css" href=" ...

  6. Android项目实战(四十四):Zxing二维码切换横屏扫描

    原文:Android项目实战(四十四):Zxing二维码切换横屏扫描 Demo链接 默认是竖屏扫描,但是当我们在清单文件中配置横屏显示的时候: <activity android:name=&q ...

  7. UWP ListView

    ListViewItem项填充整个宽度最大化<ListView.ItemContainerStyle> <Style TargetType="ListViewItem&qu ...

  8. 使用IntelliJ IDEA开发SpringMVC网站(四)用户管理

    原文:使用IntelliJ IDEA开发SpringMVC网站(四)用户管理 摘要 通过对用户表的管理,更加深入地讲解SpringMVC的操作. 目录[-] 文章已针对IDEA 15做了一定的更新,部 ...

  9. LINQ查询表达式---------group子句

    LINQ查询表达式---------group子句 LINQ表达式必须以from子句开头,以select或group子句结束.使用guoup子句来返回元素分组后的结果.group 子句返回一个 IGr ...

  10. 变量的选择——Lasso&Ridge&ElasticNet

    对模型参数进行限制或者规范化能将一些参数朝着0收缩(shrink).使用收缩的方法的效果提升是相当好的,岭回归(ridge regression,后续以ridge代称),lasso和弹性网络(elas ...