JVM内存结构 JVM的类加载机制

- protected synchronized Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- // 首先检查该name指定的class是否有被加载
- Class c = findLoadedClass(name);
- if (c == null) {
- try {
- if (parent != null) {
- // 如果parent不为null,则调用parent的loadClass进行加载
- c = parent.loadClass(name, false);
- } else {
- // parent为null,则调用BootstrapClassLoader进行加载
- c = findBootstrapClass0(name);
- }
- } catch (ClassNotFoundException e) {
- // 如果仍然无法加载成功,则调用自身的findClass进行加载
- c = findClass(name);
- }
- }
- if (resolve) {
- resolveClass(c);
- }
- return c;
- }
整个过程其实非常简单:先检查是否已经被加载过,如果没有则调用父加载器的loadClass()方法,如果父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载器加载失败,则先抛出ClassNotFoundException,然后再调用自己的findClass()方法进行加载。
自定义类加载器:若要实现自定义类加载器,只需要继承java.lang.ClassLoader 类,并且重写其findClass()方法即可。

双亲委派模型的工作过程为:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。
能不能自己写个类叫java.lang.System?
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的生命周期包括了:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称链接。[加载,链接,初始化]

加载(装载)、验证、准备、初始化和卸载这五个阶段顺序是固定的,类的加载过程必须按照这种顺序开始,而解析阶段不一定;它在某些情况下可以在初始化之后再开始,这是为了运行时动态绑定特性(例如接口只在调用的时候才知道具体实现的是哪个子类)。
1.加载:
1)通过“类全名”来获取定义此类的二进制字节流
2)将字节流所代表的静态存储结构转换为方法区的运行时数据结构
3)在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口
相对于类加载过程的其他阶段,加载阶段是开发期可控性最强的阶段,因为加载阶段可以使用系统提供的类加载器(ClassLoader)来完成,也可以由用户自定义的类加载器完成,开发人员可以通过定义自己的类加载器去控制字节流的获取方式。
加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区之中。然后在java堆中实例化一个java.lang.Class类的对象,这个对象作为程序访问方法区中的这些类型数据的外部接口。
2.验证:
验证是链接阶段的第一步,这一步主要的目的是确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全。
3.准备:
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。这个阶段中有两个容易产生混淆的知识点,首先是这时候进行内存分配的仅包括类变量(static 修饰的静态变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在java堆中。其次是这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量定义为:
public static int value = 12;
那么变量value在准备阶段过后的初始值为0而不是12,因为这时候尚未开始执行任何java方法,而把value赋值为12的putstatic指令是程序被编译后,存放于类构造器<clinit>()方法之中,所以把value赋值为12的动作将在初始化阶段才会被执行。
上面所说的“通常情况”下初始值是零值,那相对于一些特殊的情况,如果类字段的字段属性表中存在ConstantValue属性,那在准备阶段变量value就会被初始化为ConstantValue属性所指定的值,建议上面类变量value定义为:
public static final int value = 12;
4.解析
解析阶段是虚拟机常量池内的符号引用替换为直接引用的过程。
这些符号(如int a = 5中的a)就是符号引用,而解析过程就是把它转换成指向堆中的对象地址的逻辑地址。
5.初始化:
类的初始化阶段是类加载过程的最后一步,在准备阶段,类变量已赋过一次系统要求的初始值,而在初始化阶段,则是根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程。在以下四种情况下初始化过程会被触发执行:
1.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需先触发其初始化。生成这4条指令的最常见的java代码场景是:使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候,以及调用类的静态方法的时候。
2.使用java.lang.reflect包的方法对类进行反射调用的时候
3.当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先触发其父类的初始化
4.jvm启动时,用户指定一个执行的主类(包含main方法的那个类),虚拟机会先初始化这个类
JVM内存结构 JVM的类加载机制的更多相关文章
- JVM内存结构/JVM运行时数据区,以及堆内存的划分
1.程序计数器: 程序计数器是线程私有的内存,JVM多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,当线程切换后需要恢复到正确的执 行位置(处理器)时,就是通过程序计数器来实现的.此内存区域 ...
- java面试-JVM内存结构
一.JVM内存结构 二.类加载(classLoader)机制 java中的ClassLoader详解 java类加载机制面试题 java类加载机制面试题 虚拟机把描述类的数据从Class文件加载到内存 ...
- 面试~jvm(JVM内存结构、类加载、双亲委派机制、对象分配,了解垃圾回收)
一.JVM内存结构 ▷ 谈及内存结构各个部分的数据交互过程:还可以再谈及生命周期.数据共享:是否GC.是否OOM 答:jvm 内存结构包括程序计数器.虚拟机栈.本地方法栈.堆.方法区:它是字节码运行时 ...
- 管中窥豹——从对象的生命周期梳理JVM内存结构、GC调优、类加载、AOP编程及性能监控
如题,本文的宗旨既是透过对象的生命周期,来梳理JVM内存结构及GC相关知识,并辅以AOP及双亲委派机制原理,学习不仅仅是海绵式的吸收学习,还需要自己去分析why,加深对技术的理解和认知,祝大家早日走上 ...
- JVM内存结构,运行机制
三月十号,白天出去有事情出去了一天,晚上刚到食堂就接到阿里电话, 紧张到不行,很多基础的问题都不知道从哪里说了orz: 其中关于JVM内存结构,运行机制,自己笔记里面有总结的,可当天还是一下子说不出来 ...
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
前言: 我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构 ...
- 第一章 JVM内存结构
注意:本系列博客,主要参考自以下四本书 <分布式Java应用:基础与实践><深入理解Java虚拟机(第二版)><深入分析Java web技术内幕><实战jav ...
- JVM入门——JVM内存结构
一.java代码编译执行过程 1.源码编译:通过Java源码编译器将Java代码编译成JVM字节码(.class文件) 2.类加载:通过ClassLoader及其子类来完成JVM的类加载 3.类执行: ...
- JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)
转载注明出处: http://blog.csdn.net/cutesource/article/details/5904501 JVM工作原理和特点主要是指操作系统装入JVM是通过jdk中Java.e ...
随机推荐
- 转:解决Python2.7的UnicodeEncodeError: ‘ascii’ codec can’t encode异常错误
操作SQL数据库,Python使用的是版本2.7,但是在运行的时候出现了异常错误UnicodeEncodeError:'ascii' codec can't encode characters in ...
- 分页技巧_抽取出公共的分页用的Service方法
分页技巧_抽取出公共的分页用的Service方法 TopicAction.java ForumAction.java 放在父类中DaoSupport.java DaoSupportImpl.java ...
- iOS开发之--改变系统导航的颜色,字体,还有返回样式的自定义
在写项目的工程中,我们可能会遇到各种各样的项目,写的方法也是各有不同,不喜欢自定义的小伙伴也很多, 下面我就记录下系统导航和barbuttonitem的修改系统空间的方法: 1,添加rightbarb ...
- 利用MFC实现浏览器的定制与扩展(JavaScript与C++交互)
原文地址:http://www.vckbase.com/document/viewdoc/?id=1486 浏览器的定制与扩展 作者:李汉鹏 下载源代 码 本文分如下章节: 前 言 在 ...
- eclipse 的代码着色插件 --Eclipse Color Theme
Eclipse Color ThemeEclipse自带的背景颜色是白色的,很伤眼睛,故而安装一个颜色和主题插件,来改变代码区域的背景颜色以及关键字的颜色. 网址:http://eclipsecolo ...
- Bootstrap CSS组组件架构的设计思想
w AO模式 Append Overwrite 附加重写
- 经常会碰到css的bug
1.a标签做为空的时候,只做链接的时候,ie是无法点击链接. a{background:url(about:blank);} ;filter:alpha(opacity=0);} 2.给导航做下拉菜单 ...
- python基础-第五篇-5.4正则表达式
正则基础知识 正则表达式是通过调用re模块实现的 在python里,正则表达式处理对象为字符串,所以正则里方法和字符串的方法有很多相似的地方:re.findall和find,re.split和spli ...
- 剑指Offer——平衡二叉树
题目描述: 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 分析: 平衡二叉树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质 ...
- appium+python自动化测试真机测试时报错“info: [debug] Error: Could not extract PIDs from ps output. PIDS: [], Procs: ["bad pid 'uiautomator'"]”
刚开始启动服务时,弹出授权提示,以为是手机app权限问题,后来debug后,发现了一个警告日志:UiAutomator did not shut down fast enough, calling i ...