带你深入详解 JVM 内存模型与 JVM 参数详细配置,flutterpageview 预加载
一、JVM 内存结构
由上图可以清楚的看到 JVM 的内存空间分为 3 大部分:
堆内存
方法区
栈内存
其中栈内存可以再细分为 java 虚拟机栈和本地方法栈,堆内存可以划分为新生代和老年代,新生代中还可以再次划分为 Eden 区、From Survivor 区和 To Survivor 区。
其中一部分是线程共享的,包括 Java 堆和方法区;另一部分是线程私有的,包括虚拟机栈和本地方法栈,以及程序计数器这一小部分内存。
堆内存(Heap)
java 堆(Java Heap)是 Java 虚拟机所管理的内存中最大的一块。堆是被所有线程共享的区域,是在虚拟机启动时创建的。堆里面存放的都是对象的实例(new 出来的对象都存在堆中)。
此内存区域的唯一目的就是存放对象实例(new 的对象),几乎所有的对象实例都在这里分配内存。
堆内存分为两个部分:年轻代和老年代。我们平常所说的垃圾回收,主要回收的就是堆区。更细一点划分新生代又可划分为 Eden 区和 2 个 Survivor 区(From Survivor 和 To Survivor)。
下图中的 Perm 代表的是永久代,但是注意永久代并不属于堆内存中的一部分,同时 jdk1.8 之后永久代已经被移除。
新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值可以通过参数 –XX:NewRatio 来指定 )
默认的,Eden : from : to = 8 : 1 : 1 ( 可以通过参数 –XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的新生代空间大小,from = to = 1/10 的新生代空间大小。
方法区(Method Area)
方法区也称”永久代“,它用于存储虚拟机加载的类信息、常量、静态变量、是各个线程共享的内存区域。
在 JDK8 之前的 HotSpot JVM,存放这些”永久的”的区域叫做“永久代(permanent generation)”。永久代是一片连续的堆空间,在 JVM 启动之前通过在命令行设置参数-XX:MaxPermSize 来设定永久代最大可分配的内存空间,默认大小是 64M(64 位 JVM 默认是 85M)。
随着 JDK8 的到来,JVM 不再有 永久代(PermGen)。但类的元数据信息(metadata)还在,只不过不再是存储在连续的堆空间上,而是移动到叫做“Metaspace”的本地内存(Native memory。
方法区或永生代相关设置
-XX:PermSize=64MB 最小尺寸,初始分配
-XX:MaxPermSize=256MB 最大允许分配尺寸,按需分配
XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled 设置垃圾不回收
默认大小
-server 选项下默认 MaxPermSize 为 64m
-client 选项下默认 MaxPermSize 为 32m
虚拟机栈(JVM Stack)
java 虚拟机栈是线程私有,生命周期与线程相同。创建线程的时候就会创建一个 java 虚拟机栈。
虚拟机执行 java 程序的时候,每个方法都会创建一个栈帧,栈帧存放在 java 虚拟机栈中,通过压栈出栈的方式进行方法调用。
栈帧又分为一下几个区域:局部变量表、操作数栈、动态连接、方法出口等。平时我们所说的变量存在栈中,这句话说的不太严谨,应该说局部变量存放在 java 虚拟机栈的局部变量表中。java 的 8 中基本类型的局部变量的值存放在虚拟机栈的局部变量表中,如果是引用型的变量,则只存储对象的引用地址。
本地方法栈(Native Stack)
本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的 Native 方法服务。
程序计数器(PC Register)
程序计数器就是记录当前线程执行程序的位置,改变计数器的值来确定执行的下一条指令,比如循环、分支、方法跳转、异常处理,线程恢复都是依赖程序计数器来完成。Java 虚拟机多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。为了线程切换能恢复到正确的位置,每条线程都需要一个独立的程序计数器,所以它是线程私有的。
直接内存
直接内存并不是虚拟机内存的一部分,也不是 Java 虚拟机规范中定义的内存区域。jdk1.4 中新加入的 NIO,引入了通道与缓冲区的 IO 方式,它可以调用 Native 方法直接分配堆外内存,这个堆外内存就是本机内存,不会影响到堆内存的大小。
二、JVM 内存参数设置
-Xms 设置堆的最小空间大小。
-Xmx 设置堆的最大空间大小。
-Xmn:设置年轻代大小
-XX:NewSize 设置新生代最小空间大小。
-XX:MaxNewSize 设置新生代最大空间大小。
关于面试的充分准备
一些基础知识和理论肯定是要背的,要理解的背,用自己的语言总结一下背下来。
虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这
《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,我能明显感觉到国庆后多了很多高级职位,所以努力让自己成为高级工程师才是最重要的。
好了,希望对大家有所帮助。
接下来是整理的一些 Android 学习资料,有兴趣的朋友们可以关注下我免费领取方式。
①Android 开发核心知识点笔记
②对标“阿里 P7” 40W+年薪企业资深架构师成长学习路线图
③面试精品集锦汇总
④全套体系化高级架构视频
**Android 精讲视频领取学习后更加是如虎添翼!**进军 BATJ 大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务 Curd 而已!现如今市场上初级程序员泛滥,这套教程针对 Android 开发工程师 1-6 年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶 Android 中高级、架构师对你更是如鱼得水!
评论