更新时间:2021年03月18日 08时58分23秒 来源:黑马程序员论坛
一、JVM 内存结构 包括: 方法区(也就是 “持久代”),java8 里彻底被移除,取而代之的是元数据区 堆 栈(在 hotspot JVM 中,JVM 方法栈 --Java 虚拟栈,与本地方法栈是同一个) PC 寄存器(程序计数器) 还有一块: 直接内存:直接向系统内存申请的一块内存区域,javaNIO 会使用,速度优于 java 堆内存。- 隶属于物理内存,不属于 JVM 内存 注意点: 堆是 GC 的主要区域,方法区、直接内存也会发生 GC 栈与 PC 寄存器是每个线程都会创建的私有区域,不会 GC 直接内存使用速度高于堆内存,但是内存的申请速度低于堆内存 二、方法区 存放内容(类的信息、类 static 属性、方法、常量池) 已经加载的类的信息(名称、修饰符等) 类中的 static 变量 类中的 field 信息 类中定义为 final 常量 类中的方法信息 运行时常量池:编译器生成的各种字面量和符号引用(编译期)存储在 class 文件的常量池中,这部分内容会在类加载之后进入运行时常量池,class 文件的常量池查看 第三章 类文件结构与 javap 的使用 使用实例:反射,在程序中通过 Class 对象调用 getName 等方法获取信息数据时,这些信息数据来源于方法区。 调节参数 -XX:PermSize:指定方法区的最小值,默认为 16M -XX:MaxPermSize:指定方法区的最大值,默认为 64M 所抛错误 方法区域要使用的内存超过了其允许的大小时,抛出OutOfMemoryError 内存回收的主要目标 对类的卸载(这也是为什么很多企业使用 velocity 等模板引擎做前端而不是使用 jsp 的原因之一) 针对常量池的回收 总结 类中的 static 变量会在方法区分配内存,但是类中的实例变量不会(类中的实例变量会随着对象实例的创建一起分配在堆中,当然若是基本数据类型的话,会随着对象的创建直接压入操作数栈) 关于方法区的存放内容,可以这样去想所有的通过 Class 对象可以反射获取的都是从方法区获取的(包括 Class 对象也是方法区的,Class 是该类下所有其他信息的访问入口) 三、堆 存放内容 对象实例(类中的实例变量会随着对象实例的创建一起分配在堆中,当然若是基本数据类型的话,会随着对象的创建直接压入操作数栈) 数组值 使用实例 所有通过 new 创建的对象都在这块儿内存分配,具体分配到年轻代还是年老代需要根据配置参数而定(新建对象直接分配到年老代有两种情况,看下边) 调节参数 -Xmx:最大堆内存,默认为物理内存的 1/4 但小于 1G -Xms:最小堆内存,默认为物理内存的 1/64 但小于 1G -XX:MinHeapFreeRatio,默认当空余堆内存小于最小堆内存的 40% 时,堆内存增大到 - Xmx -XX:MaxHeapFreeRatio,当空余堆内存大于最大堆内存的 70% 时,堆内存减小到 - Xms 注意点 在实际使用中,-Xmx 与 - Xms 配置成相等的,这样,堆内存就不会频繁的进行调整了 抛出错误 OutOfMemoryError:在堆中没有内存完成实例分配(关于实例内存的分配,之后再说),此时堆内存已达到最大无法扩展时。 堆内存划分 新生代 组成:Eden+From(S0)+To(S1) -Xmn:整个新生代的大小 -XX:SurvivorRatio:调整 Eden:From (To) 的比率,默认为 8:1 年老代 新建对象直接分配到年老代,两种情况 大对象:-XX:PretenureSizeThreshold(单位:字节)参数来指定大对象的标准,在 Parallel Scavenge GC 下可能无效 大数组:数组中的元素没有引用任何外部的对象 总结 企业开发中,-Xmx==-Xms 通常,-Xmx 设置为 2048m 就没问题了,当然还要根据自己的程序去预估,并在运行过程中去调整,这里以在 Resin 服务器中配置为例 View Code 可以看到,-Xms==-Xmx2048m,年轻代大小 - Xmn512m,这样,年老代大小就是 2048-512==1536m,这个比率值得记住,在企业开发中,年轻代:年老代 ==1:3,而此时,我们配置的 -XX:MaxTenuringThreshold=15(这也是默认值), 年轻代对象经过 15 次的复制后进入到年老代(关于这一点,在之后的 GC 机制中会说), 四、栈 注意点 每条线程都会分配一个栈,每个栈中有多个栈帧(每一个方法对应一个栈帧) 线程创建的时候创建一个线程的 java 栈 每个方法在执行的同时都会创建一个栈帧,每个栈帧用于存储当前方法的局部变量表、操作数栈等,每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程,说的更明白一点,就是方法执行时创建栈帧,方法结束时释放栈帧所占内存 存放内容 局部变量表:八大基本数据类型数据、对象引用。该空间在编译期已经分配好,运行期不变。 操作数栈:是执行引擎直接操作的部分 调节参数 -Xss:设置栈的大小,通常设置为 1m 就好 支持 native 方法执行(本地方法栈) 所抛错误 StackOverFlowError:线程请求的栈深度大于虚拟机所允许的深度。 栈的深度就是方法调用嵌套的层数,受限于 - Xss 的大小 典型场景:没有终止条件的递归(递归基于栈)。 每个方法的栈的深度在 javac 编译之后就已经确定了 OutOfMemoryError:虚拟机栈可以动态扩展,如果扩展的时候无法申请到足够的内存。 需要注意的是,栈可以动态扩展,但是栈中的局部变量表不可以。 五、PC寄存器(程序计数器) 概念:当前线程所执行的字节码的行号指示器,用于字节码解释器对字节码指令的执行。 多线程:通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个时刻,一个处理器(也就是一个核)只能执行一条线程中的指令,为了线程切换后能恢复到正确的执行位置,每条线程都要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。 |
推荐了解热门学科
java培训 | Python人工智能 | Web前端培训 | PHP培训 |
区块链培训 | 影视制作培训 | C++培训 | 产品经理培训 |
UI设计培训 | 新媒体培训 | 产品经理培训 | Linux运维 |
大数据培训 | 智能机器人软件开发 |
传智播客是一家致力于培养高素质软件开发人才的科技公司,“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。
传智播客从未停止思考
传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”
中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。
何为中高级程序员课程?
传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展。“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。
黑马程序员热门视频教程【点击播放】
Python入门教程完整版(懂中文就能学会) | 零起点打开Java世界的大门 |
C++| 匠心之作 从0到1入门学编程 | PHP|零基础入门开发者编程核心技术 |
Web前端入门教程_Web前端html+css+JavaScript | 软件测试入门到精通 |