jvm

JVM类加载机制

廉价感情. 提交于 2020-04-08 08:46:30
JVM类加载机制 JVM类加载机制分为:加载,验证,准备,解析,初始化五步,如 下图: 加载:这个阶段会在内存中生成一个代表这个类的java.lang.Class对象作为方法区这个类的各种数据的入口。 验证:目的去报Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机的自身安全。 准备:该阶段为类变量分配内存并设置类变量的初始值,即在 方法区中分配这些变量所使用的内存空间。 解析:指虚拟机将常量池中的符号引用替换为直接引用的过程(比如说方法的符号引用,是有方法名和相关描述符组成,在解析阶段,JVM把符号引用替换成一个指针,这个指针就是直接引用,它指向该类的该方法在方法区中的内存位置) 初始化:为类的静态变量赋予正确的初始值。当静态变量的等号右边的值是一个常量表达式时,不会调用static代码块进行初始化。只有等号右边的值是一个运行时运算出来的值,才会调用static初始化. 以下几种情况不会执行初始化操作 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化 定义对象数组,不会触发该类的初始化 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触 发定义常量所在的类 通过类名获取Class 对象,不会触发类的初始化 通过Class.forName 加载指定类时,如果指定参数initialize 为false 时

JVM内容整合

爱⌒轻易说出口 提交于 2020-04-08 00:48:55
前言: JVM全称Java Virtual Machine是虚构的计算机,也是因此Java才可在各个系统平台运行,本文内容篇幅较长主要分为JVM整体流程,内存划分及组成以及JVM机制等方面进行介绍     一、JVM整体流程 一个java文件执行的大致步骤流程如下: 一张复杂的JVM架构图:   JVM加工类过程 加载 将class字节码文件加载进虚拟机,存储至元空间的方法区内 验证 文件格式验证 元数据验证 字节码验证 符号引用验证 准备 为类变量(static修饰)分配内存并设置初始值(指JVM默认值,例如:引用类型为null,int类型为0,不是类中指定的值) 如果类变量被final修饰,则直接赋类中定义的默认值(特殊情况:该final静态变量如果需要计算,会导致初始化) 成员变量(实例变量、属性、属于对象)不分配内存 解析 将常量池的符号引用转为直接引用(由于java为值传递,去掉了指针) 初始化 给类变量赋值(类中定义的默认值) 初始化静态语句块   相关题目测试 class GrandParent3{ static { System.out.println("GrandParent3静态代码块"); } } class Parent3 extends GrandParent3{ public final static String parent3="hello

jvm主内存与工作内存

白昼怎懂夜的黑 提交于 2020-04-07 19:49:08
一、jvm主内存与工作内存 首先,JVM将内存组织为主内存和工作内存两个部分。 主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的栈和对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。 1.所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共享的。 2.每条线程都有自己的工作内存,工作内存中保存的是主存中某些变量的拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。 3.线程之间无法直接访问对方的工作内存中的变量,线程间变量的传递均需要通过主内存来完成。 JVM规范定义了线程对内存间交互操作: Lock(锁定):作用于主内存中的变量,把一个变量标识为一条线程独占的状态。 Read(读取):作用于主内存中的变量,把一个变量的值从主内存传输到线程的工作内存中。 Load(加载):作用于工作内存中的变量,把read操作从主内存中得到的变量的值放入工作内存的变量副本中。 Use(使用):作用于工作内存中的变量,把工作内存中一个变量的值传递给执行引擎。 Assign(赋值):作用于工作内存中的变量,把一个从执行引擎接收到的值赋值给工作内存中的变量。 Store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传送到主内存中。 Write(写入)

Java - JVM - jstat 简单使用

拟墨画扇 提交于 2020-04-07 12:32:27
概述 jstat 的简单使用 背景 jvm 是面试经常被问到的东西 面试造火箭 的典型 面试完了, 基本不用, 所以就会被渐渐忘记 我一直觉得, 这些监控工具, 是 性能调优 的基础 看都看不清, 后续根本没法做 环境 OS win10 Java 1.8.0_201 demo Spring Boot 2.1.3 shell win10 cmd 1. 准备 jps 作用 查找 java 进程的 pid jstat 命令需要基于 java 进程的 pid 2. jstat 概述 jstat 是什么 jstat Java 工具 统计 运行时 jvm 的信息 信息 内存信息 堆栈容量 gc 信息 编译信息 其他 3. 基本格式 概述 命令基本格式 这里只讲 本地调试 格式 # option 是命令行选项 # pid 是目标进程的 pid # interval 是时间间隔, 单位是 ms > jstat <option> <pid> [interval] 例子 # 假设 pid 是 18436 # 1. 没有 interval, 只执行一次 > jstat -class 18436 # 2. interval = 1000ms, 每隔 1s 执行一次 # 可以通过使用单位 s 来调整, 这个我就不细说了 > jstat -class 18436 1000 4. 简单使用 概述 简单使用命令

JVM中垃圾回收机制如何判断是否死亡?详解引用计数法和可达性分析

老子叫甜甜 提交于 2020-04-07 11:42:50
一、前言   我们都知道Java和C++有一个非常大的区别就是Java有自动的垃圾回收机制,经过半个多世纪的发展,Java已经进入了“自动化”时代,让使用者只需要注重业务逻辑的开发而不需要担心内存的使用情况。那么我们为什么还要学习Java的垃圾回收机制呢?原因很简单:我们不想止于“增删改查工程师”这样的初级水平,一旦程序发生了内存溢出、内存泄漏等问题时,我们可以用已掌握的知识更好的调节和优化我们的代码。在学这章节之前,默认大家已经了解并掌握了Java内存运行时的五个区域的功能:方法区、Java堆、虚拟机栈、本地方法栈、程序计数器。还没有了解过的朋友请先看这里: JVM中五大内存区域 二、判断对象是否死亡 客官们可以先想一下,GC(垃圾回收机制)在清理内存的时候第一件事要做什么?肯定是要先判断内存中的对象是否已经死亡,也就是再也不会被使用了,然后才会去回收这些对象。判断对象是否死亡通常会有两种办法: 引用计数法 和 可达性分析 。 2.1 引用计数法 使用引用计数法,要先给每一个对象中添加一个计数器,一旦有地方引用了此对象,则该对象的计数器加1,如果引用失效了,则计数器减1。这样当计数器为0时,就代表此对象没有被任何地方引用。这种方法实现简单,判定效率也很高,在大部分情况下都是一个比较不错的方法。但是在Java虚拟机中并没有选用引用计数法来管理内存

类加载器ClassLoader-2

南楼画角 提交于 2020-04-07 04:13:27
类装载器 大纲: n class装载验证流程 n 什么是类装载器ClassLoader n JDK中ClassLoader默认设计模式 n 打破常规模式 n 热替换 class装载验证流程: n 加载 n 链接 – 验证 – 准备 – 解析 n 初始化 加载 n 装载类的第一个阶段 n 取得类的二进制流 [z1] n 转为方法区数据结构 n 在 Java 堆中生成对应的 java.lang.Class 对象 链接 验证 n 链接 -> 验证 – 目的: 保证 Class 流的格式是正确的 文件格式的验证 n 是否以 0xCAFEBABE 开头 n 版本号是否合理 元数据验证 n 是否有父类 n 继承了 final 类? n 非抽象类实现了所有的抽象方法 1, 什么是元数据: 举例: 任何文件系统中的数据分为数据和元数据。数据是指普通文件中的实际数据 ,而 元数据指用来描述一个文件的特征的系统数据 , 诸如访问权限、文件拥有者以及文件数据块的分布信息 (inode...) 等等。 在集群文件系统中,分布信息包括文件在磁盘上的位置以及磁盘在集群中的位置。 用户需要操作一个文件必须首先得到它的元数据 , 才能定位到文件的位置并且得到文件的内容或相关属性。 2, 元数据最大的好处是 , 它使信息的描述和分类可以实现格式化 , 从而为机器处理创造了可能。 3, 元数据概念:

JVM类加载器机制与类加载过程

烈酒焚心 提交于 2020-04-07 03:53:59
该文章是我转载的,不过我对文中的一些地方有不同的理解,所以修改几处,还请作者见谅。 原贴:http://m.blog.csdn.net/article/details?id=50529868 读完本文,你将了解到: 一、为什么说Java语言是跨平台的 二、Java虚拟机启动、加载类过程分析 三、类加载器有哪些?其组织结构是怎样的? 四、双亲加载模型的逻辑和底层代码实现是怎样的? 五、类加载器与Class<T> 实例的关系 六、线程上下文加载器 一、为什么说Java语言是跨平台的? Java语言之所以说它是跨平台的、可以在当前绝大部分的操作系统平台下运行,是因为Java语言的运行环境是在Java虚拟机中。 Java虚拟机消除了各个平台之间的差异,只要操作系统平台下安装了Java虚拟机,那么使用Java开发的东西都能在其上面运行。如下图所示: Java虚拟机对各个平台而言,实质上是各个平台上的一个可执行程序。例如在windows平台下,java虚拟机对于windows而言,就是一个java.exe进程而已。 二、Java虚拟机启动、加载类过程分析 下面我将定义一个非常简单的java程序并运行它,来逐步分析java虚拟机启动的过程。 package org.luanlouis.jvm.load; import sun.security.pkcs11.P11Util; /** *

JVM讲解(一)

会有一股神秘感。 提交于 2020-04-07 01:43:13
一、JVM的历史和背景 二、JVM的执行过程 JVM在整个JDK中处于在最底层,负责与操作系统交互,用来屏蔽操作系统环境,提供一个完整的java程序运行环境。操作系统装入JVM是通过jdk中Java.exe来完成的,通过以下四个步骤完成JVM环境的执行 1)、创建JVM装在环境和配置,2)、装载JVM.dll 3)、初始化JVM.dll并获得JNIENV接口4)、调用JNIEnv实例装载并找到类的Main()方法去处理。如下图所示: 三、JVM的基本结构 1、类装载器 (classLoader,用来装载.class文件) 2、执行引擎(执行字节码,或者执行本地方法) 3、内存空间(方法区、java堆、java栈,本地方法栈) 4、PC寄存器 (用于存储每个线程下一步将执行的JVM指令) 5、垃圾回收器 内存空间和PC寄存器组成了运行时数据区。如下图所示: 运行时数据区讲解: 1、PC寄存器 每个线程拥有一个寄存器 在线程创建时创建 用于存储每个线程下一步将执行的JVM指令 执行native方法时,则PC寄存器不存储任何信息,值为undefined 2、方法区域(method Area) 在JDK中这块区域和永久区(PermanetGeneration)关联起来,又叫持久代 保存类装载信息(名称、修饰符等)、类中的静态变量(static修饰)、final修饰的常量、字段(field

直通大厂:Java必考系列——JVM经典面试题目(含答案)

五迷三道 提交于 2020-04-06 23:22:00
Q1:类的加载机制是什么? 答:类加载到内存中主要有5个阶段,分别为 ①加载:将Class文件读取到运行时数据区的方法区内,在堆中创建Class对象,并封装类在方法区的数据结构的过程。 ②验证:主要用于确保Class文件符合当前虚拟机的要求,保障虚拟机自身的安全,只有通过验证的Class文件才能被JVM加载。 ③准备:主要工作是在方法区中为类变量分配内存空间并设置类中变量的初始值。④解析:将常量池中的符号引用替换为直接引用。 ⑤初始化:主要通过执行类构造器的<client>方法为类进行初始化,该方法是在编译阶段由编译器自动收集类中静态语句块和变量的赋值操作组成的。JVM规定,只有在父类的<client>方法都执行成功后,子类的方法才可以被执行。在一个类中既没有静态变量赋值操作也没有静态语句块时,编译器不会为该类生成<client>方法。 Q2:有哪些类加载器,类加载器的加载模型是什么,有什么好处? 答:①主要有启动类加载器,负责加载JAVA_HOME/lib中的类库;扩展类加载器,负责加载JAVA_HOME/lib/ext中的类库;应用程序类加载器,也称系统类加载器,负责加载用户类路径上指定的类库;也可以自定义类加载器。②类加载器之间的层次关系叫做双亲委派模型,要求除了顶层的启动类加载器外其余的类加载器都应当有自己的父类加载器。一个类收到类加载请求后会层层找父类加载器去尝试加载

[转]Java虚拟机支持的最大内存限制

五迷三道 提交于 2020-04-06 19:49:02
在命令行下用java -XmxXXXXM -version命令来进行测试,然后逐渐的增大XXXX的值,如果执行正常就表示指定的内存大小可用,否则会打印错误信息。 下面列出当前比较流行的几个不同公司不同版本JVM最大堆内存: 公司JVM版本 最大堆内存(兆)client 最大堆内存(兆)server Sun 1.5.x 1492 1520 Sun 1.5.5(Linux) 2634 2660 Sun 1.4.2 1564 1564 Sun 1.4.2(Linux) 2047 N/A BEA JRockit 1909 1902 Sun 1.6.0 1442 N/A 看样子用Java想用大内存也是不可能的了。而且一般的说法是内存太大了,垃圾收集的时间就会长。这也可以理解,一般是内存不够用了才收集的,扫描2G内存比1G当然要慢多了,而且内存对象多了,估计关系是指数上升的。在实际的应用中还是要自己试验一下看到底内存能达到什么样的值。 通过这个表想说明的是,如果你的机器的内存太多的话,只能通过多运行几个实例来提供机器的利用率了,例如跑Tomcat,你可以多装几个Tomcat并做集群,依此类推。 堆内存分配 JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小 于40%时,JVM就会增大堆直到-Xmx的最大限制