`

Java虚拟机JVM详解

    博客分类:
  • Java
 
阅读更多
引用

第一部分:JVM基本结构
1.什么是JVM
一个java的application对应了一个java.exe/javaw.exe(java.exe和javaw.exe你可以把它看成java的虚拟机,一个有窗口界面一个没有)。你运行几个application就有几个java.exe/javaw.exe。或者更加具体的说,你运行了几个main函数就启动了几个java应用,同时也启动了几个java的虚拟机。通过java.exe或者javaw.exe来启动一个虚拟机实例。
2.JVM的生命周期
java的虚拟机中有两种线程,一种叫叫守护线程,一种叫非守护线程,main函数就是个非守护线程,虚拟机的gc就是一个守护线程。java的虚拟机中,只要有任何非守护线程还没有结束,java虚拟机的实例都不会退出,所以即使main函数这个非守护线程退出,但是由于在main函数中启动的匿名线程也是非守护线程,它还没有结束,所以jvm没办法退出。

package com.jvm.sym;

public class TestJVM {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				for (int i = 0; i < 5; i++) {
					try {
						Thread.currentThread().sleep(i * 10000);
						System.out.println("睡了" + i * 10 + "秒");
					} catch (InterruptedException e) {
						System.out.println("干嘛吵醒我");
					}
				}
			}
		}).start();

		for (int i = 0; i < 50; i++) {
			System.out.print(i);
		}
	}

}
/*打印结果:0睡了0秒
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849睡了10秒
睡了20秒
睡了30秒
睡了40秒
*/


引用

3.JVM的体系结构
如下图所示:图一
4.JVM体系各个模块之间的调用情况:
图二
当一个classLoder启动的时候,classLoader的生存地点在jvm中的堆,然后它会去主机硬盘上将A.class装载到jvm的方法区,方法区中的这个字节文件会被虚拟机拿来new A字节码(),然后在堆内存生成了一个A字节码的对象,然后A字节码这个内存文件有两个引用一个指向A的class对象,一个指向加载自己的classLoader
5.方法区的功能
如图三

//举例方法区功能
    package test;import java.io.Serializable;public final class ClassStruct extends Object implements Serializable {//1.类信息  
     //2.对象字段信息  
     private String name;  
     private int id;  
       
     //4.常量池  
     public final int CONST_INT=0;  
        public final String CONST_STR="CONST_STR";  
          
        //5.类变量区  
        public static String static_str="static_str";  
          
       
     //3.方法信息  
     public static final String getStatic_str ()throws Exception{  
      return ClassStruct.static_str;  
     }}  


引用

其实内存的字节码块就是完整的把整个类装到了内存而已
    a.类信息:修饰符(public final)

                        是类还是接口(class,interface)

                        类的全限定名(Test/ClassStruct.class)

                        直接父类的全限定名(java/lang/Object.class)

                        直接父接口的权限定名数组(java/io/Serializable)

      也就是 public final class ClassStruct extends Object implements Serializable这段描述的信息提取

       b.字段信息:修饰符(pirvate)

                            字段类型(java/lang/String.class)

                            字段名(name)

        也就是类似private String name;这段描述信息的提取

       c.方法信息:修饰符(public static final)

                          方法返回值(java/lang/String.class)

                          方法名(getStatic_str)

                          参数需要用到的局部变量的大小还有操作数栈大小(操作数栈我们后面会讲)

                          方法体的字节码(就是花括号里的内容)

                          异常表(throws Exception)

       也就是对方法public static final String getStatic_str ()throws Exception的字节码的提取
       d.常量池:

                   d.1.直接常量:

                                   1.1CONSTANT_INGETER_INFO整型直接常量池public final int CONST_INT=0;

                                   1.2CONSTANT_String_info字符串直接常量池   public final String CONST_STR="CONST_STR";

                                   1.3CONSTANT_DOUBLE_INFO浮点型直接常量池

                                   等等各种基本数据类型基础常量池(待会我们会反编译一个类,来查看它的常量池等。)

                     d.2.方法名、方法描述符、类名、字段名,字段描述符的符号引用

            也就是所以编译器能够被确定,能够被快速查找的内容都存放在这里,它像数组一样通过索引访问,就是专门用来做查找的。

            编译时就能确定数值的常量类型都会复制它的所有常量到自己的常量池中,或者嵌入到它的字节码流中。作为常量池或者字节码流的一部分,编译时常量保存在方法区中,就和一般的类变量一样。但是当一般的类变量作为他们的类型的一部分数据而保存的时候,编译时常量作为使用它们的类型的一部分而保存

      e.类变量:

                  就是静态字段( public static String static_str="static_str";)

                  虚拟机在使用某个类之前,必须在方法区为这些类变量分配空间。

      f.一个到classLoader的引用,通过this.getClass().getClassLoader()来取得为什么要先经过class呢?思考一下,然后看第七点的解释,再回来思考

      g.一个到class对象的引用,这个对象存储了所有这个字节码内存块的相关信息。所以你能够看到的区域,比如:类信息,你可以通过this.getClass().getName()取得

          所有的方法信息,可以通过this.getClass().getDeclaredMethods(),字段信息可以通过this.getClass().getDeclaredFields(),等等,所以在字节码中你想得到的,调用的,通过class这个引用基本都能够帮你完成。因为他就是字节码在内存块在堆中的一个对象

      h.方法表,如果学习c++的人应该都知道c++的对象内存模型有一个叫虚表的东西,java本来的名字就叫c++- -,它的方法表其实说白了就是c++的虚表,它的内容就是这个类的所有实例可能被调用的所有实例方法的直接引用。也是为了动态绑定的快速定位而做的一个类似缓存的查找表,它以数组的形式存在于内存中。不过这个表不是必须存在的,取决于虚拟机的设计者,以及运行虚拟机的机器是否有足够的内存
4.总结:
首先,当一个程序启动之前,它的class会被类装载器装入方法区(不好听,其实这个区可叫做Permanent区),执行引擎读取方法区的字节码自适应解析,边解析就边运行(其中一种方式),然后pc寄存器指向了main函数所在位置,虚拟机开始为main函数在java栈中预留一个栈帧(每个方法都对应一个栈帧),然后开始跑main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行的时候,操纵系统会为本地方法分配本地方法栈,用来储存一些临时变量,然后运行本地方法,调用操作系统API等。
第二部分:JVM的各个模块的功能
在这个之前首先考虑下Java的内存管理系统,由于Java的内存管理系统实际包含两方面的内容:内存的分配和垃圾的回收。由于Java采用的自动的内存管理方式,程序员不用考虑内存管理的细节,那为什么需要去了解呢?原因有三个:
a.由于在新的线程创建时,JVM会为每个线程创建一个专属的栈(stack),这样就要求不能用过多的递归,容易导致stack overflow。
b.一旦内存出现问题,容易找到根源。
c.有优化JVM,使得优化应用。
下面就分别将各个模块:
1.类装载子系统:负责把类从硬盘上中装入内存的方法区;
2.垃圾收集器:主要是收回不再允许的程序引用对象所占用的内存,它可能负责还在使用的对象,以减少堆对象。
3.执行引擎:有四种方式:
a、最简单的:一次性解释字节码。
b、快,但消耗内存的:“即时编译器”,第一次被执行的字节码会被编译成机器代码,放入缓存,以后调用可以重用。
c、自适应优化器,虚拟机开始的时候会解释字节码,但是会监视运行中程序的活动,并记录下使用最频繁的代码段。程序运行的时候,虚拟机只把使用最频繁的代码编译成本地代码,其他的代码由于使用的并不频繁,继续保留为字节码--由虚拟机继续解释他们。一般可以使java虚拟机80%~90%的时间里执行被优化过的本地代码,只需要编译10%~20%对性能优影响的代码。
d、由硬件芯片组成,他用本地方法执行java字节码,这种执行引擎实际上是内嵌在芯片里的。 
4.pc寄存器:JVM的PC寄存器的功能是存放将要执行指令的地址。每个JVM支持多个线程同时进行,每个JVM都有自己的PC寄存器。在任何一个点,每个JVM线程执行单个方法的代码,这个方法是线程的当前方法。如果方法不是native的,程序计数器寄存器包含了当前执行的JVM指令的地址,如果方法是 native的,程序计数器寄存器的值不会被定义。
5.栈
JVM是基于栈的虚拟机.JVM为每个新创建的线程都分配一个栈.也就是说,对于一个Java程序来说,它的运行就是通过对栈的操作来完成的。栈以帧为单位保存线程的状态。JVM对栈只进行两种操作:以帧为单位的压栈和出栈操作。
6.堆:
每一个Java应用都唯一对应一个JVM实例,每一个实例唯一对应一个堆。应用程序在运行中所创建的所有类实例或数组都放在这个堆中,并由应用所有的线程共享.跟C/C++不同,Java中分配堆内存是自动初始化的。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在堆栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
6.1栈和堆的比较:
栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方 。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。
栈的优势是,存取速度比堆要快 ,仅次于直接位于CPU中的寄存器。
堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。
数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。
7.方法区:
VM有一个被所有的线程共享方法区。方法区类似于传统语言的编译后代码的存储区,或者UNIX进程中的text段。它存储每个类结构例如常量池(constant pool),成员字段域和方法和构造函数,包含类和实例初始化和接口类型类型中用到的特殊方法的代码。
方法区在虚拟机启动时创建。尽管方法区在逻辑上时heap的一部分,简单的实现仍然可以选择对它既不回收也不压缩。

引用

JVM监控
1.jstatd
启动jvm监控服务。它是一个基于rmi的应用,向远程机器提供本机jvm应用程序的信息。默认端口1099。
2.jps
列出所有的jvm实例
3.jconsole
一个图形化界面,可以观察到java进程的gc,class,内存等信息。虽然比较直观,但是个人还是比较倾向于使用jstat命令
4.jinfo(linux下特有)
观察运行中的java程序的运行环境参数:参数包括Java System属性和JVM命令行参数
5.jmap(linux下特有,也是很常用的一个命令)
观察运行中的jvm物理内存的占用情况。
6.jstat
这是jdk命令中比较重要,也是相当实用的一个命令,可以观察到classloader,compiler,gc相关信息
  • 大小: 80.1 KB
  • 大小: 270.2 KB
  • 大小: 63 KB
分享到:
评论

相关推荐

    java虚拟机JVM详解ppt

    通过对Java虚拟机JVM的基本概念、架构以及内存管理机制的深入解析,我们可以更好地理解Java程序的执行过程。掌握JVM的工作原理有助于开发者编写更高效、更稳定的Java应用程序,并能有效地解决常见的内存溢出问题。

    Java 虚拟机JVM内存模型

    ### Java 虚拟机JVM内存模型知识点 #### 1. JVM概述 ##### 1.1 Java的特性与JVM的应用 Java语言的特性包括跨平台性、面向对象、安全性等。JVM是Java程序能够跨平台运行的关键,它负责将Java源代码转换成与平台无关...

    JVM内幕:java虚拟机详解

    ### JVM内幕:java虚拟机详解 #### 一、概述 Java虚拟机(JVM)是运行Java应用程序的核心组件,它提供了一个可移植、安全且高性能的环境。本文将深入探讨JVM的内部架构及其各个组成部分的功能。 #### 二、Java虚拟机...

    jvm详解(java虚拟机详解)

    ### jvm详解(java虚拟机详解) #### Java与JVM概览 Java作为一种广泛使用的编程语言,其核心优势之一便是“一次编写,到处运行”的特性,这背后的关键技术支撑即为Java虚拟机(JVM)。JVM是一种抽象计算模型,允许...

    JVM(Java虚拟机)详解.pdf

    JVM(Java虚拟机)详解 一、JVM 概念 JVM(Java虚拟机)是一个抽象的计算模型,提供了一个运行环境,能够运行 Java 字节码。JVM 可以解读指令代码并与底层进行交互,包括操作系统平台和执行指令并管理资源的硬件...

    java虚拟机jvm及Tomcat中的jvm有关内存的设置与调优

    ### Java虚拟机(JVM)内存设置与调优详解 #### 引言 在现代软件开发中,Java虚拟机(JVM)作为执行Java字节码的核心组件,其性能直接影响到Java应用的运行效率与稳定性。特别是在大数据处理场景下,合理设置JVM内存...

    JAVA虚拟机解读入门

    《JAVA虚拟机解读入门》是一本面向初学者的指南,旨在带领读者深入理解Java虚拟机(JVM)的工作原理和内部机制。JVM是Java语言的核心组成部分,它为Java程序提供了一个跨平台的运行环境,使得“一次编写,到处运行”...

    深入Java虚拟机JVM类加载学习笔记

    ### 深入Java虚拟机JVM类加载学习笔记 #### 一、Classloader机制解析 在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及...

    读书笔记:java虚拟机详解jvm从入门到精通.zip

    读书笔记:java虚拟机详解jvm从入门到精通

    Java虚拟机工作原理详解

    Java虚拟机工作原理详解 Java虚拟机工作原理详解是 Java 程序执行的核心组件之一。了解 Java 虚拟机的工作原理对 Java 开发人员来说非常重要。本文将详细介绍 Java 虚拟机工作原理的详细过程和类加载器的工作机理。...

    Java虚拟机JVM参数配置说明.pdf

    ### Java虚拟机(JVM)参数配置详解 #### 引言 在Java及J2EE大型应用的场景下,Java虚拟机(JVM)非标准参数的合理配置对于提升系统的整体性能至关重要。这些参数不仅影响着应用的运行效率,还直接关联到系统的稳定性...

    java虚拟机原理详解1

    一本非常好的详细介绍java虚拟机实现原理及详细介绍的的好书 有兴趣了解JVM底层知识的看看,太大了,分三部分,都下了才能解压

    java虚拟机原理详解3

    一本非常好的详细介绍java虚拟机实现原理及详细介绍的的好书 有兴趣了解JVM底层知识的看看,太大了,分三部分,都下了才能解压

    实战JAVA虚拟机 JVM故障诊断与性能优化

    ### 实战JAVA虚拟机:JVM故障诊断与性能优化 #### 一、引言 在当今高度依赖软件系统的环境中,Java作为一种广泛使用的编程语言,在企业级应用开发中扮演着极其重要的角色。Java虚拟机(JVM)作为Java程序运行的...

    java虚拟机参数详解

    Java虚拟机(JVM)是Java程序运行的基础,它负责解释和执行字节码,管理内存,以及执行垃圾收集等任务。本篇文章将详细解析Java虚拟机的一些关键参数及其作用,帮助开发者更好地理解和优化JVM的性能。 1. **-XX:+...

    全面理解JVM虚拟机.pdf

    全面理解JVM虚拟机.pdf

    java虚拟机详解免费.pdf

    Java技术自诞生以来就以其“一次编写,到处运行”的理念而备受赞誉,而这一理念的核心实现正是Java虚拟机(JVM)。...因此,JVM详解不仅是Java学习者必须掌握的知识,也是提升Java应用性能的有力工具。

    java虚拟机详解.docx

    ### Java虚拟机(JVM)详解 #### 一、Java技术概览 Java不仅仅是一种编程语言,更是一项由多个组成部分构成的技术。这些组成部分包括Java编程语言、Java类文件格式、Java虚拟机(JVM)以及Java应用程序接口(API)。它们...

    Java虚拟机(JVM)面试题详解及其技术要点

    内容概要:本文档系统地梳理了与Java虚拟机(JVM)相关的常见面试题目及其解答,详细讲解了JVM的概念、主要组成部分(类加载器、运行时数据区、执行引擎、本地方法接口)、内存模型各部分的用途以及各类垃圾收集器的...

    Java虚拟机(JVM)面试题 51道.pdf

    Java虚拟机(JVM)是Java语言的核心组成部分,它为Java程序提供了一个跨平台的运行环境。以下是对JVM相关知识点的详细解释: 1. **Java代码的执行过程**: - 开发人员编写的Java代码首先通过`javac`编译器转化为`....

Global site tag (gtag.js) - Google Analytics