阅读量 : 59次
一、JVM中的内存区域划分
JVM 本质上是一个 java 进程,Java 进程会从操作系统申请一大块区域给 Java 代码使用。这一大块区域会进行划分,主要划分为堆、栈、方法区1元数据区。具体分为:
堆:存放对象实例(所有被 new 出来的对象)
栈:存放方法调用的栈(局部变量、方法的参数、返回地址等)
方法区1元数据区:存储类元数据(类结构、方法代码、静态变量、常量池等)
程序计数器:记录当前线程执行的字节码指令地址(即JVM指令的行号)
本地方法栈:为执行本地方法(Native Method,如JNI调用)提供栈帧
虚拟机栈:执行 Java 代码
如上图所示,对基本的内存区域划分图,下面来详细解释每个区域对应的工作。
1.堆,主要是 new 出来的对象即成员变量
2.栈,主要是用来维护方法之间的调用即局部变量
3.方法区1元数据区,方法在内存中是按照一些二进制指令的形式来存储的(字节码),特殊情况热加载机制需要在字节码维度做出一些特殊的处理。因此它是类和加载之后的类对象(.class文件、Test.class文件)(静态变量等)
4.虚拟机栈, 给 Java 代码使用的
5.本地方法栈,给JVM 内部的本地方法使用(JVM内部通过C++方法实现)
6.程序计数器,记录当前程序指定到哪个指令,使用简单的 long 类型存储了一个内存地址,内存地址就是下一个要执行的字节码所在的地址
我们在编写 Java 代码时,会产生一份线程,这个线程会同时在操作系统和 Java 虚拟机存在,在 java 层面会在虚拟机栈存一份线程,而操作系统层面会在本地方法栈存一份。
此外,堆区和元数据区,在一个JVM 进程中只有一份。而栈(本地方法栈和虚拟机栈)和程序计数器是有多份的。
2.2 类加载什么时候会触发?
类加载机制并不是 JVM 一启动就把 .class 文件都加载了,而是通过一个“懒加载”的机制(懒汉模式)即非必要不加载,必要:
创建了这个类的实例
使用了这个类的静态方法/静态属性
使用子类,会触发父类的加载
2.3 双亲委派模型
双亲委派模型为在第一个步骤加载中出现的问题,在加载中找到 .class 文件的过程。
JVM中,加载类 需要用到一组特殊的模块,类加载器。JVM中 内置了三个类加载器:
1.BootStrap ClassLoader负麦加载 Java 标准库中的类
2.Extension ClassLoader 负载加载一些非标准的但是 Sun/ Oracle 扩展库的类3.Application ClassLoader加载项目中自己写的类,以及第三方库中的类
加载一个类的过程为:
先给定一个类的全限定类名“java.long.String"的字符串,并把问题抛给 Application ClassLoaderApplication ClassLoader 作为"儿子"再把问题抛给 Extension ClassLoader ,Extension ClassLoader 作为“父亲"再把问题抛给 BootStrap ClassLoader ,BootStran ClassLoader 作为"答" 而它上方为,nul 比时就会自行处理问题,处理不了则把问题抛给"父亲"Exten.,依次类推,直到某一步能解决问题则执行后续的2345步骤否则则抛出一个异常“ClassNotFoundException"。以上的流程类似于,员工在处理问题时依次向上通报。
下一篇:
 返回顶部
    返回顶部