1. Java虚拟机的概述和基本概念

1.1  Java虚拟机原理

所谓虚拟机,就是一台虚拟的机器。它是一款软件,用来执行一系列虚拟计算机指令,大体上虚拟机可以分为系统虚拟机和程序虚拟机,大名鼎鼎的VisualBox/VMare就属于系统虚拟机,他们完全是对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。程序虚拟机代表就是Java虚拟机,它专门为执行单个计算机程序而设计,在Java虚拟机中执行的指令,我们称为Java字节码指令。无论是系统虚拟机还是程序虚拟机,在上面运行的软件都被限制于虚拟机提供的资源中。Java发展至今,出现过很多虚拟机,最初Sun使用的一款叫Classic的Java虚拟机,到现在应用最广泛的是HotSpot虚拟机,除了Sun以外,还有BEA的JRockit,目前JRockit和HotSpot都被Oracle收入旗下,大有整合的趋势。

1.2 Java虚拟机的基本结构及加载顺序(不同版本的jvm内存结构可能不同,这里用的是jdk8)

类加载子系统:负责从文件系统或者网络中加载Class信息,加载的信息存放在一块称之为方法区的内存空间。

方法区:(所有线程共享这个区的数据)就是存放类信息、常量信息、常量池信息、包括字符串字面量和数字常量等。

Java堆:在Java虚拟机启动的时候建立Java堆,它是Java程序中最主要的k内存工作区域,几乎所有的对象实例都存放在Java堆中,堆空间是所有线程共享的。

直接内存:Java的NIO库允许Java程序使用直接内存,从而提高性能,通常内存速度会优于Java堆。读写频繁的场合可能会考虑使用。

Java栈:每个虚拟机线程都有一个私有的栈,一个线程的java栈在线程创建的时候被创建,java栈中保存着局部变量、方法参数、同时java的方法调用、返回值等。

本地方法栈:本地方法栈和Java栈非常类似,最大不同为本地方法栈用于本地方法调用。java虚拟机允许java直接调用本地方法(通常使用C编写)

垃圾回收系统:垃圾收集系统是Java的核心,也是必不可好的,java有一套自己进行垃圾清理的机制,开发人员无需手工清理,文章下面会有详细说明。

PC寄存器:(Program Counter)寄存器也会每个线程私有的空间,java虚拟机会为每个线程创建PC寄存器,在任意时刻,一个Java线程总是在执行一个方法,这个方法被称为当前方法,如果当前方法不是本地方法,PC寄存器就会执行当前正在执行的命令,如果是本地方法,则PC寄存器值为undefined,寄存器存放如当前执行环境指针、程序计数器、操作栈指针、计算的变量指针等信息。

执行引擎:虚拟机最核心的组件就是执行引擎了,它负责执行虚拟机的字节码。一般用户先进行编译成机器码后执行。

2. 堆、栈、方法区

堆:解决的是数据存储的问题,即程序如何执行,或者说如何处理数据。

栈:解决程序的运行问题,即程序如何执行,或者说如何处理数据。

方法区:辅助堆栈的快永久区,解决堆栈信息的产生,是先决条件。

我们创建一个新的对象,User:那么User类的一些信息(类信息、静态信息都存在于方法区中)

  1. 而User类被实例化出来之后,被存储到Java堆中,一块内存空间
  2. 当我们去使用的会后,都是使用User对象的引用,形如User user = new User();
  3. 这里的user就是存放在java栈中的,即User真实对象的一个引用。

简单来说:堆存对象,栈存对象的引用,方法区(线程共享)存的是对象中的常量数据


这里插一个知识点:数据共享,线程共享  (https://blog.csdn.net/qq_39404258/article/details/82459543)

数据共享的有:栈、寄存器、PC                        线程共享的有:堆、全局变量、静态变量、方法区


2.1 辨清java堆

java堆是和java应用程序关系最密切的内存空间,几乎所有的对象都存放在堆中,并且java堆完全是自动化管理的,通过垃圾回收机制,垃圾对象会自动清理,不需要显示地释放。

根据垃圾回收机制不同,java堆有可能拥有不同的结构。最为常见的就是将整个java堆分为新生代和老年代。其中新生代存放新生对象或者年龄不大的对象,老年代则存放老年对象。

新生代分别为eden(伊甸园)区,s0区,s1区,s0和s1也被称为from和to区域,他们是两块大小相等并且可以互换角色的空间。绝大多数情况下,对象首先分配在eden区,在一次新生代回收后,如果对象还存活,则会进入s0或者s1区,之后每经过一次新生代回收,如果对象存活则它的年龄就加1,当对象达到一定年龄后,则进入老年代(tenured)。

s0 和 s1 大小一样,并且可以相互转换角色。

如何确定新生代对象、老年代对象:

因为java有自动的垃圾回收机制,每当回收对象一次该对象就改变一次标识,相当于标识对象的年龄。

java中新生代的from(s0)和to(s1)空间就是使用,复制算法:其核心思想就是将内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存留对象复制到未被使用的内存块中去,之后去清除之前正在使用的内存块中所有的对象,反复去交换两个内存的角色,完成垃圾收集。

2.2 java栈

java栈是一块线程私有的内存空间,一个栈,一般由三部分组成:局部变量表、操作数栈和帧数据区。

局部变量表:用户报错函数的参数及局部变量。

操作数栈:主要保存计算过程的中间结果,同事作为计算过程中变量临时的存储空间。

帧数据:除了局部变量表和操作数栈以外,栈还需要一些数据来支持常量池的解析,这里帧数据区保存着访问常量池的指针,方便程序访问常量池,另外,当函数返回或者出现异常时,虚拟机必须有一个异常处理表,方便发送异常的时候找到异常的代码,因此异常处理表也是帧数据区的一部分。

2.3 Java方法区(Perm)

Java方法区和堆一样,方法区是一块所有线程共享的内存区域,它保存系统的类信息,比如类的字段、方法、常量池等。方法区的大小决定了系统可以保存多少个类,如果系统定义太多的类,导致方法区溢出。虚拟机同样会抛出内存溢出错误。方法区可以理解为永久区(Perm) 。


3. 了解虚拟机参数

在虚拟机运行的过程中,如果可以跟踪系统的运行状态,那么对于问题的故障排查会有一定的帮助,为此,虚拟机提供了一些跟踪系统状态的参数,使用给定的参数执行java虚拟机,就可以在系统运行事时打印相关日志,用于分析实际问题。我们进行虚拟机参数配置,其实主要就是围绕着堆、栈、方法区进行配置。

垃圾回收机制可以配置不同的垃圾回收策略。

3.1 堆分配参数(一)

-XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志。
-XX:+UseSerialGC 配置串行回收器。
-XX:+PrintGCDetails 可以查看信息信息,包括各个区的情况。
-Xms:设置Java应用程序启动时的初始堆大小
-Xmx:设置Java应用程序能获得的最大堆大小
-Xmx20m -Xms5m -XX:+PrintConnandLineFlags: 设置最大堆内存20M,初始化堆内存为5M,可以将隐式或者显示传给虚拟机的参数输出。
示例[Test01]
总结:在实际工作中,我们可以直接将初始化的堆大小与最大堆大小设置相等,这样的好处是可以减少程序运行时的垃圾回收次数,从而提高性能。

3.1.1 在哪里配置 ? 先来个初级的(先不说在linux上的设置),在idea 或者 eclipse中配置(eclipse与idea差不多)。

如果是eclipse则点击右键,run as --> configuration

下面是idea图:

设置参数为:

-XX:+PrintGC -Xmx20m -Xms5m -XX:+UseSerialGC -XX:+PrintGCDetails

Test01代码:

package com.jvm;/*** @author: wangqinmin* @date: 2019/7/23 14:50* @description: 仰天大笑出门去,我辈岂是蓬蒿人*/
public class Test01 {public static void main(String[] arge) {/*** -XX:+PrintGC 使用这个参数,虚拟机启动后,只要遇到GC就会打印日志。* -XX:+UseSerialGC 配置串行回收器。* -XX:+PrintGCDetails 可以查看信息信息,包括各个区的情况。* -Xms:设置Java应用程序启动时的初始堆大小* -Xmx:设置Java应用程序能获得的最大堆大小* -Xmx20m -Xms5m -XX:+PrintConnandLineFlags: 设置最大堆内存20M,初始化堆内存为5M,可以将隐式或者显示传给虚拟机的参数输出。* 示例[Test01]* 总结:在实际工作中,我们可以直接将初始化的堆大小与最大堆大小设置相等,这样的好处是可以减少程序运行时的垃圾回收次数,从而提高性能。*/// 使用这个参数进行配置。//-XX:+PrintGC -Xmx20m -Xms5m -XX:+UseSerialGC -XX:+PrintGCDetailsSystem.out.println("jvm启动后遇到GC就会打印日志,设置最大堆内存20M,初始化堆内存5M,使用串行回收器,查看jvm各个区的情况");double a = (double) Runtime.getRuntime().maxMemory();System.out.println("最大内存:" + a / 1024 / 1024 / 1024 + "G");System.out.println();// 查看GC信息System.out.println("max memory:" + Runtime.getRuntime().maxMemory() + "B,转换为KB:" + Runtime.getRuntime().maxMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "M");System.out.println("free memory:" + Runtime.getRuntime().freeMemory() + "B,转换为KB:" + Runtime.getRuntime().freeMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().freeMemory() / 1024 / 1024 + "M");System.out.println("total memory:" + Runtime.getRuntime().totalMemory() + "B,转换为KB:" + Runtime.getRuntime().totalMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "M");System.out.println();// 查看完信息后,实例化一个1M大小的对象byte[] b1 = new byte[1 * 1024 * 1024];// 查看GC信息System.out.println("示例化一个1M的对象");System.out.println("max memory:" + Runtime.getRuntime().maxMemory() + "B,转换为KB:" + Runtime.getRuntime().maxMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "M");System.out.println("free memory:" + Runtime.getRuntime().freeMemory() + "B,转换为KB:" + Runtime.getRuntime().freeMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().freeMemory() / 1024 / 1024 + "M");System.out.println("total memory:" + Runtime.getRuntime().totalMemory() + "B,转换为KB:" + Runtime.getRuntime().totalMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "M");System.out.println();// 查看完信息后,实例化一个4M大小的对象byte[] b2 = new byte[4 * 1024 * 1024];// 查看GC信息System.out.println("示例化一个4M的对象");System.out.println("max memory:" + Runtime.getRuntime().maxMemory() + "B,转换为KB:" + Runtime.getRuntime().maxMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "M");System.out.println("free memory:" + Runtime.getRuntime().freeMemory() + "B,转换为KB:" + Runtime.getRuntime().freeMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().freeMemory() / 1024 / 1024 + "M");System.out.println("total memory:" + Runtime.getRuntime().totalMemory() + "B,转换为KB:" + Runtime.getRuntime().totalMemory() / 1024 + "KB,转换为M:" + Runtime.getRuntime().totalMemory() / 1024 / 1024 + "M");System.out.println();/**
控制台打印数据:*"C:\Program Files\Java\jdk1.8.0_152\bin\java.exe" -XX:+PrintGC -Xmx20m -Xms5m -XX:+UseSerialGC -XX:+PrintGCDetails "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.4\lib\idea_rt.jar=6067:C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_152\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_152\jre\lib\rt.jar;E:\2019MyProject\dust\out\production\dust1;C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.4\lib\junit-4.12.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2018.1.4\lib\hamcrest-core-1.3.jar" com.jvm.Test01* [GC (Allocation Failure) [DefNew: 1664K->191K(1856K), 0.0010359 secs] 1664K->672K(5952K), 0.0010621 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]* 最大内存:0.0189208984375G** max memory:20316160B,转换为KB:19840KB,转换为M:19M* free memory:4973104B,转换为KB:4856KB,转换为M:4M* total memory:6094848B,转换为KB:5952KB,转换为M:5M** 示例化一个1M的对象* max memory:20316160B,转换为KB:19840KB,转换为M:19M* free memory:3924512B,转换为KB:3832KB,转换为M:3M* total memory:6094848B,转换为KB:5952KB,转换为M:5M** [GC (Allocation Failure) [DefNew: 1661K->76K(1856K), 0.0011371 secs][Tenured: 1696K->1773K(4096K), 0.0013115 secs] 2142K->1773K(5952K), [Metaspace: 3412K->3412K(1056768K)], 0.0024785 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]* 示例化一个4M的对象* max memory:20316160B,转换为KB:19840KB,转换为M:19M* free memory:4285616B,转换为KB:4185KB,转换为M:4M* total memory:10358784B,转换为KB:10116KB,转换为M:9M** Heap*  def new generation   total 1920K, used 79K [0x00000000fec00000, 0x00000000fee10000, 0x00000000ff2a0000)
新生代中的eden区:*   eden space 1728K,   4% used [0x00000000fec00000, 0x00000000fec13cc0, 0x00000000fedb0000)
新生代中的s0区:*   from space 192K,   0% used [0x00000000fedb0000, 0x00000000fedb0000, 0x00000000fede0000)
新生代中的s1区:*   to   space 192K,   0% used [0x00000000fede0000, 0x00000000fede0000, 0x00000000fee10000)
老年代区tenured:*  tenured generation   total 8196K, used 5869K [0x00000000ff2a0000, 0x00000000ffaa1000, 0x0000000100000000)*    the space 8196K,  71% used [0x00000000ff2a0000, 0x00000000ff85b520, 0x00000000ff85b600, 0x00000000ffaa1000)
元空间Metaspace:*  Metaspace       used 3461K, capacity 4500K, committed 4864K, reserved 1056768K
类空间 class space:*   class space    used 374K, capacity 388K, committed 512K, reserved 1048576K** Process finished with exit code 0*/}
}

然后确定即可,开始运行Test01程序。

3.2 堆分配参数(二)

新生代的配置

-Xmn: 可以设置新生代的大小,设置一个比较大的新生代会减少老年代的大小,这个参数对系统性能以及GC行为有很大影响,新生代大小一般会设置整个堆空间的1/3到1/4左右。
-XX:SurvivorRatio: 用来设置新生代中eden空间和from/to空间的比例。含义:-XX:SurvivorRatio=eden/from=eden/to

示例【Test02】

package com.jvm;/*** @author: wangqinmin* @date: 2019/7/23 17:57* @description: 仰天大笑出门去,我辈岂是蓬蒿人*/
public class Test02 {public static void main(String[] args) {// 第一次配置:// -Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC// 第二次配置:// -Xms20m -Xmx20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC// 第三次配置:// -XX:NewRatio=老年代/新生代// -Xms20m -Xmx20m -XX:NewRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGCbyte[] b = null;// 连续向系统申请10M空间for (int i = 0; i < 10; i++) {b = new byte[1 * 1024 * 1024];}}
}

总结:不同的堆分布情况,对系统执行会产生一定影响,在实际工作中,应该根据系统的特点做出合理的配置,基本策略:尽可能将对象预留在新生代,减少老年代的GC次数。

除了可以设置新生代的绝对大小(-Xmn),还可以使用(-XX:NewRatio)设置新生代和老年代的比例:-XX:NewRatio=老年代/新生代

第一次配置:
-Xms20m -Xmx20m -Xmn1m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC第二次配置:
-Xms20m -Xmx20m -Xmn7m -XX:SurvivorRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC第三次配置:
-XX:NewRatio=老年代/新生代
-Xms20m -Xmx20m -XX:NewRatio=2 -XX:+PrintGCDetails -XX:+UseSerialGC

某些参数认识:

-Xss:设置线程栈的大小
-XX:MinHeapFreeRatio:设置堆空间最小空闲比例。当对空间的空闲内存小于这个数值时,JVM便会扩展堆空间
-XX:MaxHeapFreeRatio:设置堆空间的最大空闲比例。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的堆
-XX:NewSize:设置新生代的大小
-XX:NewRatio:设置老年代与新生代的比例,它等于老年代大小除以新生代大小
-XX:SurvivorRatio:新生代中eden区与survivior区的比例
-XX:MaxPermSize:设置最大的持久区的大小
-XX:PermSize:设置永久区的初始值
-XX:TargetSurvivorRatio:设置survivior区的可使用率。当survivior区的空间使用率达到这个数值时,会将对象送入老年代

3.3 堆内存溢出处理

在java程序的运行过程中,如果堆空间不足,则会抛出内存溢出的错误( Out Of Menory)OOM,一旦这类问题发生在生产环境,可能引起严重的业务中断,Java虚拟机提供了-XX:+HeapDumpOnOutOfMemoryError,使用该参数可以在内存溢出时导出整个堆信息,与之配合使用的还有参数-XX:HeapDumpPath=d:/Test03.dump 这个相当于设置导出具体位置,并使用java自带的工具jdk的bin目录下的jvisualvm.exe打开文件,进行阅览。

示例【Test03】

package com.jvm;import java.util.Vector;/*** @author: wangqinmin* @date: 2019/7/23 18:11* @description: 仰天大笑出门去,我辈岂是蓬蒿人*/
public class Test03 {/*** 使用jvisualvm来分析dump文件:* jvisualvm是JDK自带的Java性能分析工具,在JDK的bin目录下,文件名就叫jvisualvm.exe。* jvisualvm可以监控本地、远程的java进程,实时查看进程的cpu、堆、线程等参数,对java进程生成dump文件,并对dump文件进行分析。* 像我这种从服务器上dump下来文件也可以直接扔给jvisualvm来分析。* 使用方式:直接双击打开jvisualvm.exe,点击文件->装入,在文件类型那一栏选择堆,选择要分析的dump文件,打开。** @param args*/public static void main(String[] args) {// 内存溢出和内存溢出原因存放位置// -Xms2m -Xmx2m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/Test03.dumpVector v = new Vector();for (int i = 0; i < 5; i++) {v.add(new Byte[1 * 1024 * 1024]);}}
}

3.4  栈调用深度

package com.jvm;/*** @author: wangqinmin* @date: 2019/7/23 19:11* @description: 仰天大笑出门去,我辈岂是蓬蒿人*/
public class Test04 {// -Xss1m// 调用最大深度:21047// -Xss5m// 调用最大深度:123178/*** 栈调用深度*/private static int count;public static void main(String[] args) {try {recursion();} catch (Throwable t) {System.out.println("调用最大深度:" + count);t.printStackTrace();}}public static void recursion() {count++;recursion();}
}

3.5 方法区

方法区和java堆一样,方法区是一块所有线程共享的内存区域,它用于保存系统的类信息, 方法区(永久区)可以保存多少信息可以对其进行配置,在默认情况下,-XX:MaxPermSize为64M, 如果系统运行时生产大量的类,就需要设置一个相对合适的方法,以免出现永久区内存溢出的问题。

-XX:PermSize=64M -XX:MaxPermSize=64M

3.6 直接内存

直接内存配置(据说jdk1.7之后可以不用配置): 直接内存也是java程序中非常重要的组成部分,特别是广泛用在NIO中,直接内存跳过了java堆,是java程序可以直接访问原生堆空间, 因此在一定程度上加快了内存空间的访问速度,但是说直接内存一定就可以提高内存访问速度也不见得,具体情况具体分析。 相关配置参数:-XX:MaxDirectMemorySize,如果不设置默认值为最大堆空间即-Xmx.直接内存使用达到上限时,就会触发垃圾回收,如果 不能有效的释放空间,也会引起系统的OOM(Out of Memory 内存泄漏)。

简单说一下:jdk1.7以后就没有Client 和 Server 虚拟机工作模式了。 Client 与 Server 模式的区别; Client模式启动快,运行期间性能低,基本做测试使用。 Server模式启动慢,优化策略较好,运行性能远远快与Client模式。

与JVM不错的博客(有总结,了解): https://www.cnblogs.com/redcreen/archive/2011/05/04/2036387.html

4. 垃圾回收概念和算法、及对象的分代转换

垃圾回收,简称GC,需要先澄清什么是垃圾,类比日常生活中的垃圾,我们会把他们丢入垃圾桶,然后倒掉,GC中的垃圾,特指存在于内存中、不会再被使用的对象,而回收就是相当于把垃圾 “倒掉” 。垃圾回收有很多算法:如引用计数算法、标记压缩算法、复制算法、分代、分区的思想。

进一步了解垃圾回收算法:

https://blog.csdn.net/newchenxf/article/details/78071804

5. 垃圾收集器 

6. Tomcat性能影响实验

7. 性能监控工具

Java虚拟机JVM相关推荐

  1. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  2. Java虚拟机JVM学习05 类加载器的父委托机制

    Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...

  3. 《深入理解Java虚拟机 - Jvm高级特性与最佳实践(第三版)》阅读笔记

    <深入理解Java虚拟机>阅读笔记 本repository为<深入理解Java虚拟机 - Jvm高级特性与最佳实践(第三版)>阅读笔记,因为第一章主要讲的是Java的发展历史, ...

  4. 深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器)

    一.什么是类加载机制? 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 二.类加载的时机 类 ...

  5. Java虚拟机JVM简单理解

    Java虚拟机JVM的作用: Java源文件(.java)通过编译器编译成.class文件,.class文件通过JVM中的解释器解释成特定机器上的机器代码,从而实现Java语言的跨平台. JVM的体系 ...

  6. [java] 虚拟机(JVM)底层结构详解[转]

    [java] 虚拟机(JVM)底层结构详解[转] 本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 在以前的博客里面,我们介绍了在java领 ...

  7. Java虚拟机JVM的内部体系结构

    JVM(Java虚拟机)是一个抽象机器. 它是一个提供可以执行Java字节码的运行时环境的规范.JVM可用于许多硬件和软件平台(即JVM是平台相关的). 什么是JVM? JVM(Java虚拟机)是: ...

  8. [转载] java虚拟机 jvm 出入java栈 栈空间内存分配

    参考链接: Java虚拟机(JVM)堆栈区域 java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调 ...

  9. java虚拟机MyEclipse_Eclipse和MyEclipse运行环境java虚拟机jvm设置,自己设置jre

    Eclipse运行环境java虚拟机jvm设置,自己设置jre 浅谈Eclipse寻找JVM(JRE)的顺序机制 Eclipse也是一个普通的Java程序,因此必须有一个JRE做为运行环境. 如果你的 ...

  10. 深入理解java虚拟机 - jvm高级特性与最佳实践(第三版)_JVM虚拟机面试指南:年薪30W以上高薪岗位需求的JVM,你必须要懂!...

    JVM的重要性 很多人对于为什么要学JVM这个问题,他们的答案都是:因为面试.无论什么级别的Java从业者,JVM都是进阶时必须迈过的坎.不管是工作还是面试中,JVM都是必考题.如果不懂JVM的话,薪 ...

最新文章

  1. 前端小白第一次使用redux存取数据练习
  2. 蓝桥杯2015初赛-星系炸弹-日期计算
  3. mfc打开一个.txt文件并进行处理_文件处理方法Python
  4. 限制python内存上限_13.14 限制内存和CPU的使用量
  5. 戴尔R730 安装升级VMware vSphere Hypervisor (ESXi) 6.7
  6. HDU 3065 病毒侵袭持续中(AC自动机 模板)题解
  7. 基于单片机的人体健康检测系统
  8. 【计算机网络】HTTP 协议详解
  9. Tomcat后台管理
  10. 乔巴机器人 番外篇_超神学院之暮光之眼
  11. 服务器ie浏览器总是未响应,win7电脑IE浏览器总是未响应怎么办 IE浏览器无响应原因解决方法...
  12. Godot着色器基础
  13. Pyhton3 下载Telegram 频道数据
  14. polplayer下载网址和polplayer直播源
  15. 嵌入式Linux(十三)RTC实时时钟
  16. Linux系统常见的发行版本以及区别!
  17. STM32智能小车------PWM驱动直流电机
  18. Mldonkey命令解释
  19. css 画小黄人,纯CSS3画出小黄人并实现动画效果
  20. KOA2项目简单搭建

热门文章

  1. 从零开始编写minecraft光影包(7)基础水面绘制
  2. 电脑如何打开软键盘,教大家Win10如何打开软键盘的方法
  3. 2021年2月世界编程语言排行榜
  4. 【MySQL】MySQL入门笔记
  5. ubuntu 20.10 下载安装教程
  6. 北京专科计算机学校排名及分数线,北京专科大学排名及分数线
  7. 在输入框输入时限制输入框只能输入正整数以及两位小数正则表达式
  8. I3D【Inflated 3D ConvNet】——膨胀卷积网络用于行为识别
  9. Sql中的left函数、right函数
  10. 因果推断笔记—— 相关理论:Rubin Potential、Pearl、倾向性得分、与机器学习异同(二)