深入java虚拟机-JVM (java virture mechine)

编程语言的层级关系

电脑硬件–>windows系统(C/C++)–>JVM虚拟机(C/C++)–>Java代码

在这里插入图片描述

JDK是工具包 ,JDK中包含jre,jre 就是JVM 虚拟机

JVM内部结构

在这里插入图片描述

  • 绿色是功能区域(真正干活的),功能(类加载,垃圾回收,执行引擎) 类加载是入口 ,执行引擎是出口。
  • 橙色是线程共享区域,每个线程进来共享的区域(包括方法区、Java堆、直接内存(java1.4非阻塞NIO之后就没了)大小受电脑内存影响),类存放在方法区,相当于模板 共享,根据模板创建类的实例对象 ,存在栈中。)
  • 蓝色是线程私有区域,每个线程进来都会开辟一个栈,当线程执行完了 ,栈、本地方法栈、pc寄存器就会销毁。没法共有,直接销毁。
    在这里插入图片描述
public class  Demo1(){   //Demo类属于模板 存在方法区,对象是类的实例
   
   public void demo1(String i){ //成员变量demo1是方法 存在栈中,形参i 是局部变量存在栈中
     
     Demo1 demo1 =  new Demo1();
   //Demo1为类  方法区
         //demo1 引用(指向 Java堆中对象的 引用地址) 栈中 
                    //new Demo1() 类的实例 java堆中
      
      int i = 1 ;  //局部变量 栈中              
   }

}

执行流程
在这里插入图片描述

类加载器

  • Bootstrap Class Loader C++写,JVM启动, 加载Java基础类,对应的文件是%JRE_HOME/lib/
    目录下的rt.jar、resources.jar、charsets.jar和class等
  • Extension Class Loader 继承URL ClassLoader 加载扩展类 对应的文件是 %JRE_HOME/lib/ext 目录下的jar和class等
  • App Class Loader 继承URL Class Loader ,系统类加载器
    对应的文件是应用程序classpath目录下的所有jar和class等
public class  Demo2(){  
  public  static void main(String[] args){
    System.out.println(HKSCS.class.getClassLoader());//bootstrap Class Loader
       
       System.out.println(ZipInfo.class.getClassLoader());//Extension Class Loader
         
          System.out.println(Demo2.class.getClassLoader());//App Class Loader
   }

}

面试题:java双亲委派机制及作用 (类加载机制)

  • 什么是双亲委派机制
    当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类
  • 双亲委派机制的作用
    1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。防止把jdk中的类覆盖。
    2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。

在这里插入图片描述

执行引擎

作用 : 执行编译后的字节码指令.
主要的执行技术有 : 解释执行,即时编译执行,自适应优化执行, 芯片级直接执行
(1)解释:属于第一代JVM;
(2)即时编译:JIT属于第二代JVM;
(3)自适应优化:(目前Sun的HotspotJVM采用这种技术)吸取第一代JVM和第二代JVM的经验,采用两者结合的方式。
开始对所有的代码都采取解释执行的方式,
并监视代码执行情况,然后对那些 经常 调用的方法启动一个后台线程,将其编译为本地代码,并进行仔细优化。
若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行;
(4)芯片级直接执行:内嵌在芯片上,用本地方法执行Java字节码。

Java栈 、本地方法栈J

两者合并为栈,主要存放动态链接、局部变量等信息,线程创建的时候,就创建栈

因为只有一个进口 和出口 ,栈中的方法是现进后出,

方法出口是指 每执行完一个方法之后要回到 调用此方法的前一个方法中,理解很抽象。

本地方法栈作用 : 用于本地方法调用, JDK源码中好多使用了Native关键字, 也就是调用底层C语言编写的方法.,这种方法是实现类的方法,但是没有方法体。合并之后存在栈中

栈中放置以下内容

栈中存放基本类型的原值和引用类型的地址值.
基本类型包括:byte,short,int,long,char,float,double,Boolean,returnAddress 引用类型包括:类类型,接口类型和数组,方法的实例
在这里插入图片描述

PC寄存器

作用 : 每个线程启动的时候,都会创建一个PC寄存器。保存下一条将要执行的指令地址. PC寄存器的内容总是指向下一条将被执行指令的地址,这里的地址可以是一个本地指针,也可以是在方法区中相对应于该方法起始指令的偏移量。

以下为线程共享区

方法区(元空间)

jdk1.8之后 就改名为元空间 ,不再占JVM的内存(1/4内存条)了,直接占内存条(16G)的内存。所以1.8之后就不会溢出

作用 : Java方法区和堆一样,方法区是一块所有线程共享的内存区域,他保存系统的类信息。比如类的字段、方法名(方法的模板,不是真实的方法)、常量池等。
方法区的大小决定系统可以保存多少个类。如果系统定义太多的类,导致方法区溢出。虚拟机同样会抛出内存溢出的错误。

Java堆

堆,栈,方法区之间的关系图:
在这里插入图片描述
堆的内部结构(垃圾回收 复制算法)
在这里插入图片描述

直接内存

作用 : 提高一些场景中的性能.
直接内存并不是虚拟机运行时数据区的一部分,也不是Java 虚拟机规范中农定义的内存区域。在JDK1.4 中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native 函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
本机直接内存的分配不会受到Java 堆大小的限制,受到本机总内存大小限制
配置虚拟机参数时,不要忽略直接内存 防止出现OutOfMemoryError异常
直接内存(堆外内存)与堆内存比较
直接内存申请空间耗费更高的性能,当频繁申请到一定量时尤为明显 直接内存IO读写的性能要优于普通的堆内存,在多次读写操作的情况下差异明显
在这里插入图片描述
未完待续……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值