JVM笔记(一)
<ignore_js_op>
Class Loader类加载器
负责加载class文件,class文件在文件开头有特定的文件标识,并且ClassLoader只负责class文件的加载,至于它是否可以运行,则由Execution Engine决定。
Method Area方法区(永久区)
方法区是被所用的线程共享,所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也是再此定义。简单说,所有定义的方法的信息都报错在该区域,此区间属于共享区间。
静态变量+常量+类信息+运行时常量池存在方法区中,它存储了每一个类的结构信息
注意:Java8去永久代,用元空间 替代。永久代使用的是JVM的堆内存,但是元空间并不在虚拟机中华而是使用本机的物理内存。
Heap堆
栈管运行,堆管存储
堆是线程共享区域,是java虚拟机管理最大的一块区域。此区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。
PC Register 程序计数器
每一个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码(下一个将要执行的指令代码),由执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不记。线程私有。此区域是唯一一个没有OutOfMemoryError(OOM)的区域。
VM Stacks 虚拟机栈
栈管运行,堆管存储
线程私有。
虚拟机栈描述的是Java方法执行的内存模型:每一个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直到执行完的过程,就对应一个栈帧在虚拟机栈中入栈到出栈的过程。
Native Method Stack 本地方法栈
它的具体做法是 Natice Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies。和虚拟机栈一样,都是线程私有的。
Native Interface
本地接口的作用是融合不同的编程语言为Java所用,它的初衷是融合C/C++程序,Java诞生的时候是C/C++横行的时候,想要立足,必须有调用C/C++程序。目前,该方法使用的越来越少了,因为现在的异构领域间的通信很发达,比如可以使用Socket通信,也可以用WebService等等。
栈:一般指虚拟机栈
1)对于栈来说不存在垃圾回收问题。
2)基本类型的变量和对象的引用变量都在函数的栈内存中分配。
栈帧
栈帧(Stack Frame)是用于支持虚拟机运行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈(Virtual Machine Stack)的栈元素。栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程。
<ignore_js_op>
堆堆内存示意图
Eden:S0:S1=8:1:1
新生代:老年代=1:2 (新生代占堆的1/3,老年代占堆的2/3)
在新生代中存活15(默认)次以上才被放入老年代中
<ignore_js_op>
堆内存调优
参数 含义 demo
-Xms 设置初始分配大小,默认为物理内存的“1/64” -Xms5m
-Xmx 最大分配内存,默认为物理内存的“1/4” -Xms20m
-XX:+PrintGCDetails 输出详细的GC处理日志 -XX:+PrintGCDetails
-XX:+PrintCommandLineFlags 可以将隐式或者显式传给虚拟机的参数输出 XX:+PrintCommandLineFlags
-Xmn 设置新生代的绝对大小,新生代一般会设置整个堆空间的1/3到1/4左右 -Xmn20m
-XX:SurvivorRatio 用来设置新生代中eden空间和form/to空间的比例 -XX:SurvivorRatio=eden/from=eden/to -XX:SurvivorRatio=2
-XX:NewRatio 设置新生代和老年代的比例 -XX:NewRatio=老年代/新生代 -XX:NewRatio=2
-Xss 制定线程的最大栈空间,整个参数也直接决定了函数课调用的最大深度 -Xss5m
-XX:MaxTenuringThreshold 新生代经过多少次GC后进入老年代,默认为15 -XX:MaxTenuringThreshold=15
-XX:PretenureSizeThreshold 设置对象的大小超过在制定的大小之后,直接晋升老年代 ,后面的1000为100k -XX:PretenureSizeThreshold=1000
在实际工作中,我们可以直接将初始的堆大小与最大堆大小设置相等,这样的好吃是可以减少程序运行时的垃圾回收次数,从而提高性能。
收集算法
口诀
频繁收集Yong区
较少收集Old区
基本不动Perm区
标记清除算法
老年代一般是由标记清除或者是标记清除与标记整理的混合实现
优点:不需要额外空间(和复试算法的缺点2比)
缺点: 1)有碎片,空闲空间不连续
2)两次扫描,效率低
3)需要一个内存空间记录哪是空,哪是非空
复制算法
年轻代中使用的Minor GC ,这种GC算法采用的是复制算法(Copying)
优点:没有碎片
缺点:1)如果对象存活率很高(极端一点,100%),将全部数据复制费时费力
2)浪费一了 survice 1 的空间
标记整理算法
老年代一般是由标记清除或者是标记清除与标记整理的混合实现
优点:无碎片,不需要额外空间
缺点:效率低,低于复制算法
垃圾收集器
<ignore_js_op>
Serial收集器
serial收集器依然是虚拟机运行在Client模式下的默认新生代收集器。
复制算法收集器。
ParNew收集器
ParNew收集器是Serial收集器的多线程版本。
复制算法收集器。
Parallel Scavenage收集器
关注点为吞吐量
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
复制算法收集器
Serial Old收集器
标记-整理算法
Serial收集器的老年版
Parallel Old收集器
标记-整理算法
在注重吞吐量和CPU资源敏感的场合,都可以优先考虑Parallel Scavenge 加 Parallel Od
Parallel Old是Parallel Scavenge收集器的老年带版本
CMS收集器
标记-清除算法
CMS收集器数一种以获取最短回收停顿时间为目标的收集器。
收集器步骤:
1)初始标记
2)并发标记
3)重新标记
4)并发清除
优点:并发收集、低停顿
缺点:CMS收集器对CPU资源非常敏感
无法处理浮动垃圾
标记-清除法的缺点,有碎片
G1收集器
特点:并发与并行、分代收集、空间整理、可预测停顿
类加载机制
<ignore_js_op>
注意:
加载会调用静态代码块
初始化会调非静态代码块和构造方法
先加载类在初始化类,加载只加载一次
加载和初始化不一样
加载的是类的模板
初试化的是类的实例对象
1)静态的大于代码块,代码块大于构造方法
静态块先执行,并且只执行一次
代码块比构造方法先执行,并行new几次运行几次(运行结果)
public class Person {
public Person() {
System.out.println("Person 构造方法");
}
static {
System.out.println("Person 静态代码块");
}
{
System.out.println("Person 普通代码块");
}
}
public class Start {
public static void main(String[] args) {
Person person = new Person();
System.out.println("-------");
Person person2 = new Person();
}
}
<ignore_js_op>
2)通过数组定义引用类,不会触发此类的加载
通过数组定义引用类,不会加载此类,因为加载此类必定会调用static静态代码快
public class Start {
public static void main(String[] args) {
Person[] persons = new Person[10];
}
}
<ignore_js_op>
3)加载子类会同时加载和初始化父类
先执行父类的静态块(看下图运行结果)
在执行子类的静态块(看下图运行结果)
在执行父类的普通块和构造方法(看下图运行结果)
最后执行子类的普通块和构造方法(看下图运行结果)
public class Man extends Person {
public Man() {
System.out.println("Man 构造方法");
}
static {
System.out.println("Man 静态代码块");
}
{
System.out.println("Man 普通代码块");
}
}
public class Start {
public static void main(String[] args) {
Man man = new Man();
}
}
<ignore_js_op>
4)通过子类引用父类的静态变量,不会导致子类加载和初始化,会导致父类加载,不会导致父类初始化
通过子类使用父类的静态变量,不会加载子类,会加载父类
会调用父类的静态代码块,不会调用父类的普通代码块
不会加载子类,自然不会调用子类的静态代码块
public class Person {
public Person() {
System.out.println("Person 构造方法");
}
static {
System.out.println("Person 静态代码块");
}
{
System.out.println("Person 普通代码块");
}
//静态成员变量
public static int value = 1024;
}
class Man extends Person {
static {
System.out.println("Man 静态代码块");
}
}
public class Start {
public static void main(String[] args) {
System.out.println(Man.value);
}
}
<ignore_js_op>
5)常量(final)在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的加载和初始化。
public class Person {
static {
System.out.println("Person 静态代码块");
}
{
System.out.println("Person 普通代码块");
}
//静态final成员变量
public static final int value = 1024;
}
public class Start {
public static void main(String[] args) {
System.out.println(Person.value);
}
}
<ignore_js_op>
更多技术资讯可关注:itheimaGZ获取
JVM笔记(一)的更多相关文章
- JVM笔记(虚拟机各内存的介绍)
JVM笔记 java代码执行分为两部分:javac编译 java执行 代码并不是由上往下执行的,会经过编译期重排序进行优化,存在依赖关系的代码不会被重排序,保证了代码最终执行结果的正确性! j ...
- JVM笔记-Java技术体系与JVM概述
1. 简述 Java 不仅仅是一门编程语言,还是一个由一系列计算机软件和规范组成的技术体系. Java 的广告词为 "一次编写,到处运行",之所以能够做到"跨平台&quo ...
- JVM笔记五-堆区
JVM笔记五-堆区 在JVM中,堆区是重中之重.通过前面文章的学习,我们知道了,栈区是不会有垃圾回收的,所以,经常说的垃圾回收,其实就是回收的是堆区的数据.在这里,我们将会看到传说中的,新生代.老年代 ...
- JVM笔记6-垃圾回收概述
JVM进行垃圾回收时要考虑哪的问题如下: 1.如何判定对象为垃圾对象? 1.引用计数法:在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,引用失效的时候,计数器的值就-1, ...
- JVM笔记(三) 垃圾收集器(2)收集算法
垃圾收集器2:收集算法 主要通过阅读<深入了解Java虚拟机>(周志明 著)和网络资源汇集而成,为本人学习JVM的笔记.同时,本文理论基于JDK 1.7版本,暂不考虑 1.8和1.9 的新 ...
- JVM笔记(二) 垃圾收集器(1)
垃圾收集器 主要通过阅读<深入了解Java虚拟机>(周志明 著)和网络资源汇集而成,为本人学习JVM的笔记.同时,本文理论基于JDK 1.7版本,暂不考虑 1.8和1.9 的新特性,但可能 ...
- JVM笔记6-垃圾回收器
JVM进行垃圾回收时要考虑哪的问题如下: 1.如何判定对象为垃圾对象? 1.引用计数法:在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,引用失效的时候,计数器的值就-1, ...
- todo JVM笔记
之前给自己定了很多计划,要学Dubbo,Netty,SSHM源码,Tomcat源码...这些基本浅尝辄止,很难继续研读,过不了多久就忘了. 觉得还是基础不够,所以决定把<JVM>.< ...
- JVM笔记【1】-- 运行时数据区
目录 (一)java内存区域管理 1.1 程序计数器 1.2 虚拟机栈 1.3 本地方法栈 1.4 java堆 1.5 方法区 1.5.1 运行时常量池 (二)直接内存 (一)java内存区域管理 C ...
- JVM笔记 -- JVM的发展以及基于栈的指令集架构
2011年,JDK7发布,1.7u4中,开始启用新的垃圾回收器G1(但是不是默认). 2017年,发布JDK9,G1成为默认GC,代替CMS.(一般公司使用jdk8的时候,会通过参数,指定GC为G1) ...
随机推荐
- ae基础二
纯色文本操作快捷键:选中图层点击快捷键(变换)锚点:a(调节中心点)位置:p(左右移动)(利用位置k帧做动画)缩放:s(水平翻转垂直翻转)旋转:r(围绕中心点(锚点)进行旋转)不透明度:tu选中索引 ...
- macbook 一些php相关操作
开启php: https://jingyan.baidu.com/article/67508eb434539f9cca1ce4da.html 配置多虚拟主机: https://jingyan.bai ...
- Oracle之纵向数据转换横向数据
资源二 来源 http://www.cnblogs.com/gkl0818/archive/2009/02/25/1398078.html 1.固定列数的行列转换如student subject ...
- Django_JavaScript
JavaScript是什么 JavaScript是一种运行在客户端(浏览器)的编程语言,用来给网页添加动态功能. JavaScript的作用 最初目的 为了处理表单的验证操作 现在广泛的应用场景 网页 ...
- 基于JSP开发医院预约挂号系统 Java源码
开发环境: Windows操作系统 开发工具: Eclipse+Jdk+Tomcat+MYSQL数据库 运行效果图: 源码及原文链接:http://javadao.xyz/forum.php?mod= ...
- goweb-表单
表单 简单的处理一个登陆界面 package main import ( "fmt" "html/template" "log" " ...
- Linux inode 理解
inode 硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB).操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性读取一 ...
- base64字符串转化成图片
package com.dhht.wechat.util; import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder; import ja ...
- Spring 如何解决循环依赖的问题
Spring 如何解决循环依赖的问题 https://blog.csdn.net/qq_36381855/article/details/79752689 Spring IOC 容器源码分析 - 循环 ...
- Win10用Windows照片查看程序(照片查看器)打开图片
以上方法只能一个个添加,也有人说不好使,这里给出一个我写的批处理程序,反正我一直用着很好. ::复制以下内容到记事本: @echo off&cd\&color 0a&cls ...