java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

Wesley13
• 阅读 807

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

上一篇讲完了java内存模型中线程私有部分(程序计数器、虚拟机栈、本地方法栈),这篇讲下所有线程公有部分

问:元空间(MetaSpace)和永久代(PermGen)的区别?

  • 元空间使用本地内存,而永久代使用的是jvm的内存

jdk8以后将类的元数据放在本地堆内存中,就是元空间MetaSpace,该空间jdk以前是属于永久代的。8以后没有OutOfMemoryError:PermGen space

元空间和永久代都是存放class的相关信息,包括class和Meta、field的信息。

元空间和永久代都是方法区的实现,只是实现不同,所以说方法区只是JVM的一种规范。

JDK1.7之后原先位于方法区中的字符串常量池已经移动到了堆中。jdk8以后使用元空间(MetaSpace)替代永久代(PermGen),因为元空间划分更合理,比如说类及相关的元数据和类加载器生命周期一致,每个加载器都会分配一个单独的内存空间。

MetaSpace相比PermGen的优势

  • 字符串常量池存在永久代中,容易出现性能问题和内存溢出
  • 类的方法信息大小难确定,给永久代的大小置顶带来困难(太小会出现永久代溢出,太大容易导致老年代溢出)
  • 永久代会为GC带来不必要的复杂性,回收效率低(永久代中的元数据的可能会随着full GC发生而进行移动,比较消耗虚拟机性能。HotSpot虚拟机的每种类型的垃圾回收器都需要特殊处理永久代中的元数据。将元数据从永久代剥离出来,不仅实现了对元空间的无缝管理,还可以简化Full GC以及对以后的并发隔离类元数据等方面进行优化)
  • 方便HotSpot与其他JVM如Jrockit的集成(永久代是hotspot特有的,别的VM没有永久代)

Java堆(Heap):

  • 对象实例的分配区域(heap是个大头,占用最多的内存空间。xmx设置jvm最大可用内存)
  • GC管理的主要区域(所以也称为GC堆)

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

jvm虚拟机规范里,java堆可以使用不连续的内存空间,只要逻辑上连续即可,就像磁盘空间一样。堆空间可以是固定大小,也可以是动态扩展的(主流的虚拟机都是动态的)。如果堆中没有内存完成实例分配,且堆不能再扩展时将会抛出OutOfMemoryError异常java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

主流的垃圾回收机制都是采用分代收集算法,所以堆可以分为新生代、老年代,再细点就有eden区、from survivor区、to survivor区,后面博客中GC再细讲。

问:jvm三大新能调优参数 -Xms -Xmx -Xss的含义?

  1. -Xss:规定了每个线程虚拟机栈(堆栈)的大小(一般256k足够,此设置会影响并发线程数大小)
  2. -Xms:堆的初始值(就是jvm进程刚启动的时候分配的堆空间大小,后面运行时堆空间超过初始值,就会动态扩容至堆的最大空间)
  3. -Xmx:堆能达到的最大值(一般xms xmx 都设置成一样的,因为xms不够用时动态扩容,会发生内存抖动,影响程序稳定性)

问:java内存模型中堆和栈的区别?

首先需要明白 内存分配策略:

  1. 静态存储:编译时确定每个数据目标在运行时的存储空间需求(这种分配策略要求程序不允许有可变存储空间的结构存在,也不允许有嵌套、递归的结构存在。因为它们都会导致编译时无法计算准确的存储空间)
  2. 栈式存储:数据区需求在编译时未知,运行时模块入口前确定(动态的存储分配,是由一个类似于堆栈的运行栈实现的,和静态的分配方式相反。但是进入一个程序模块的时候必须知道该模块的存储大小,才能对其分配内存。跟栈一样按照新进后出的方式分配内存)
  3. 堆式存储:编译时或运行时模块入口都无法确定存储空间,需要动态分配(比如可变长度串、对象实例。堆由大片的可利用快或空闲块组成,堆中的内存可以按照任意顺序分配和释放)

堆和栈的区别:

  • 联系:引用对象、数组时、栈里定义变量保存堆中目标的首地址(栈只存引用变量,类似指针,程序使用栈中的引用变量访问堆中的对象、数组。引用变量是普通变量,定义时在栈中分配,引用变量在程序运行到程序作用域之外后就会被释放掉,而数组、对象本身在堆中分配,即使程序运行到作用域之外(new或者产生数组的代码块之外)堆中的数组、对象的内存不会被释放,之后会被垃圾回收掉)
  • java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇
  • 管理方式:栈自动释放,堆需要GC(JVM自己可以针对内存栈进行管理操作,而且该内存空间的释放是编译器就可以操作的内容。而堆空间在java中,jvm执行引擎是不会对其释放的操作,而是让GC回收)
  • 空间大小:栈比堆小(栈里面存储的数据和本身需要的数据特性决定的。堆需要存储比较多的对象数据,一般都很大)
  • 碎片相关:栈产生的碎片远小于堆(堆空间的活动空间相当于栈比较大,可能存在长期的内存分配和释放操作,而且GC不是实时的,这使得堆中的碎片逐渐累积起来。栈空间本身就是堆栈数据结构,它的操作都是一一对应的,而且内存结构相对于堆空间的简单,不容易产生碎片)
  • 分配方式:栈支持静态和动态分配,而堆仅支持动态分配
  • 效率:栈的效率高于堆(因为内存块本身就是个堆栈的结构,和栈空间的结构相符合,操作也简单,只存在入栈出栈两个操作。相对于堆空间,栈空间的灵活程度不够,特别是动态管理的时候,而堆空间最大优点就是动态分配,因为它在计算机底层可能是个双向链表的结构,所以管理的时候操作比栈复杂很多,所以堆的效率低于栈,但是灵活度高了很多)

例子:

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

**问:不同JDK版本的intern()方法的区别?(主要是JDK6 VS JDK6+)**String.intern()是一个Native方法,底层调用C++的 StringTable::intern 方法,源码注释:当调用 intern 方法时,如果常量池中已经该字符串,则返回池中的字符串;否则将此字符串添加到常量池中,并返回字符串的引用。

例子:

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

JDK6的时候存在永久代,所以VM options可以设置PermSize大小

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

运行就会内存溢出,这也证明了JDK6存在永久代且永久代里面由字符串常量池

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

JDK7 永久代移到堆中了 所以没有内存溢出的错误

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

JDK8 也能输出Mission Complete 但是没有永久代的设置了 java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

intern在jdk6和6+的区别

java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

jdk7+是java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

jdk6是java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

详情请看:https://www.jianshu.com/p/0d1c003d2ff5 或者 https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这