关于java的类加载机制加载顺序,这个东西可以说是基础的东西,不过很遗憾这方面很多人也都不是很在意,比如我自己,最近上班闲下来了,就开始看一些博客文章了,今天恰好被一篇博文给吸引了,并且他的示例题一开始自己完全答错了,于是就开始深入进去看他的文章,也是园区里面的一位叫 陈树义 老哥的文章,链接如下:https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html

本文倒不是打算纯转载,而是看了他的博文的之后算是一篇观后感吧,也算是自己的一篇学习笔记一样的东西,加上一些自己白话的理解,方便自己日后复习,如果想要深入学习的,建议去他的博文里仔细看下,他写的很好,篇幅虽长但是耐心看下去其实并不难理解,写的挺到位的。

首先,关于java类加载,他原文说是七个阶段:加载、验证、准备、解析、初始化、使用、卸载。

关于这几个阶段,我着重理解了下  验证,准备,初始化  这三个阶段:

验证:此时进行代码逻辑校验,例如  int a=Intege.valueOf("aaa");  这种代码运行报错应该是在这个阶段。

准备:此时给一些static修饰的变量分配内存,并给予它们相应的初始0值,如static int a=5,在这个阶段会先赋予0,如果是String类型则赋予null,但是如果还有final修饰的话,则会直接赋予定义的值。

初始化:此时开始正式执行我们的代码,并且对一些类进行实例化,他文章里的原文描述很到位,其原文如下:

  • 遇到 new、getstatic、putstatic、invokestatic 这四条字节码指令时,如果类没有进行过初始化,则需要先触发其初始化。生成这4条指令的最常见的Java代码场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候,以及调用一个类的静态方法的时候。
  • 使用 java.lang.reflect 包的方法对类进行反射调用的时候,如果类没有进行过初始化,则需要先触发其初始化。
  • 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先触发其父类的初始化。
  • 当虚拟机启动时,用户需要指定一个要执行的主类(包含main()方法的那个类),虚拟机会先初始化这个主类。
  • 当使用 JDK1.7 动态语言支持时,如果一个 java.lang.invoke.MethodHandle实例最后的解析结果 REF_getstatic,REF_putstatic,REF_invokeStatic 的方法句柄,并且这个方法句柄所对应的类没有进行初始化,则需要先出触发其初始化。

好了,基础理论知识就如上所示,下面用代码实例进行对应讲解,首先测试代码如下:

 public class FSY {
static FSY fsy=new FSY();
static String age = "20";
String name = "小A";
//普通代码块,声明类时就执行一次,在构造之前执行,多个普通代码块则按顺序执行
{
System.out.println("普通代码块");
}
//静态代码块,在类初始化时执行,且仅执行这一次,多个也是按顺序执行
static {
System.out.println("静态代码块"+age);
}
//构造代码块
FSY(){
System.out.println("声明了一个人 ,姓名"+name+",年龄"+age);
}
//实体方法
void say(){
System.out.println(age+"岁的"+name+"说话了");
}
public static void main(String[] args) {
fsy.say();
}
}

最后的输出结果是:

 普通代码块
声明了一个人 ,姓名小A,年龄null
静态代码块20
20岁的小A说话了

然后说下我理解的代码执行步骤:

1.首先,“加载”,“验证”这两步略过说明,开始“准备”阶段,该阶段会给一些static修饰的变量分配内存,并赋予初始值,则此时运行了如下代码:

 static FSY fsy = null;
static String age = null;

2.随后,略过“解析”阶段说明,开始了“初始化”阶段。

初始化阶段总的来说,优先执行static修饰的所有变量,即静态块,相关代码如下:

 static FSY fsy=new FSY();
static String age = "20";
//静态代码块,在类初始化时执行,且仅执行这一次,多个也是按顺序执行
static {
System.out.println("静态代码块"+age);
}
//个人感觉main方法不在此列

按照静态块的顺序,首先执行:

 static FSY fsy=new FSY();

此时涉及到了声明该对象,所以执行其构造块,按顺序组装其执行的构造块如下:

 String name = "小A";
//普通代码块,声明类时就执行一次,在构造之前执行,多个普通代码块则按顺序执行
{
System.out.println("普通代码块");
}
//构造代码块
FSY(){
System.out.println("声明了一个人 ,姓名"+name+",年龄"+age);
}
//实体方法
void say(){
System.out.println(age+"岁的"+name+"说话了");
}

因为say方法暂时没人调用,所以其内部的语句并没有打印出来,而此时age仅分配了内存,赋予了初始null值。

然后继续按照静态块的顺序,开始给age赋值,

 static String age = "20";

随后调用它的静态代码块,

 //静态代码块,在类初始化时执行,且仅执行这一次,多个也是按顺序执行
static {
System.out.println("静态代码块"+age);
}

最后,执行main方法里面的语句,

public static void main(String[] args) {
fsy.say();
}

大致理解就如上面所述,可以看出,我将静态代码块也当作是一个静态变量来看待其执行顺序,也不知道是否正确,也没想好怎么验证。

文中部分结论我是直接拷贝的,还希望别说我直接盗文啥的,其实我是按照万一他的那个网页被404了来考虑的,不希望有些资料的缺漏,以前也收藏过一些博客的文章,结果人家博客搬家了,找不到了,挺遗憾的。

另外不得不说他在他那篇博客的评论里有回复一位园友的话语也是一块挺重要的知识,我也想摘抄一下,怕他啥时候搬家我找不到了,他们的对话如下图:

最后再次重复提一下,本文只是相当于我的一篇学习记录,描述角度也是偏重于我自己容易理解的角度,可能其他朋友看上去会有些散乱,如果有想要仔细学习这一块的话,还是建议去看下他的那篇文章,很详细很明了。

当然了,如果我文中有错误的话,还请指出来,我尽早也改掉,免得以后复习错误的知识。。。。。万分感谢。

------------------------------------------------20180612修改分隔线-------------------------------------

发现一个重大问题。。上面原文的加载顺序我理解有误,虽然结果是对的,但是刚才进行全断点跑的时候却发现他优先跑的没有static修饰的代码,后跑的有static修饰的代码。。。待我整理好思绪后修改该文。。。/(ㄒoㄒ)/~~

------------------------------------------------20180613修改分隔线-------------------------------------

虚惊一场,昨天在陈树义老哥的博客下进行了相应的提问,然后通过他的回答以及自己重新修改了下测试代码,经测试并没有错,还好还好,是原先断点打错了,直接用的老哥的测试代码,换了下顺序,如下图:

可以看出在跑Book的init方法前,amount已经先赋值了,原先以为自己理解错了是因为static 实体类方法写在最上面,且断点没打上,结果导致显得好像先跑了init方法,即构造块

关于java类加载机制的一些理解的更多相关文章

  1. 理解Java类加载机制(译文)

    理解java类加载机制 你想写类加载器?或者你遇到了ClassCastException异常,或者你遇到了奇怪的LinkageError状态约束异常.应该仔细看看java类的加载处理了. 什么是类加载 ...

  2. Java类加载机制的理解

    算上大学,尽管接触Java已经有4年时间并对基本的API算得上熟练应用,但是依旧觉得自己对于Java的特性依然是一知半解.要成为优秀的Java开发人员,需要深入了解Java平台的工作方式,其中类加载机 ...

  3. 深入理解和探究Java类加载机制

    深入理解和探究Java类加载机制---- 1.java.lang.ClassLoader类介绍 java.lang.ClassLoader类的基本职责就是根据一个指定的类的名称,找到或者生成其对应的字 ...

  4. 深入理解Java类加载机制,再也不用死记硬背了

    谈谈"会"的三个层次 在<说透分布式事务>中,我举例里说明了会与会的差别.对一门语言的学习,这里谈谈我理解的"会"的三个层次: 第一层:了解这门语言 ...

  5. Java类加载机制深度分析

    转自:http://my.oschina.net/xianggao/blog/70826 参考:http://www.ibm.com/developerworks/cn/java/j-lo-class ...

  6. 两道面试题,带你解析Java类加载机制

    文章首发于[博客园-陈树义],点击跳转到原文<两道面试题,带你解析Java类加载机制> 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Gr ...

  7. 【转】两道面试题,带你解析Java类加载机制(类初始化方法 和 对象初始化方法)

    本文转自 https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html 关键语句 我们只知道有一个构造方法,但实际上Ja ...

  8. Java类加载机制与Tomcat类加载器架构

    Java类加载机制 类加载器 虚拟机设计团队把类加载阶段中的“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类.实现这 ...

  9. 带你解析Java类加载机制

      目录 Java类加载机制的七个阶段 加载 验证 准备(重点) 解析 初始化(重点) 使用 卸载 实战分析 方法论 树义有话说 在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如 ...

随机推荐

  1. 贝叶斯公式由浅入深大讲解—AI基础算法入门

    1 贝叶斯方法 长久以来,人们对一件事情发生或不发生的概率,只有固定的0和1,即要么发生,要么不发生,从来不会去考虑某件事情发生的概率有多大,不发生的概率又是多大.而且概率虽然未知,但最起码是一个确定 ...

  2. ubuntu16.04SSH无法连接

    提示错误:server responded "algorithm negotiation failed” 解决办法: 修改ssh的配置文件 /etc/ssh/sshd_config文件 在末 ...

  3. JavaScript笔记1———js的一些常识

    一.什么是js? js是一种运行于解释器中的解释型脚本语言. 二.js的组成部分? 1.ECMAScript-----这是js的核心 2.DOM-----让js可以对网页进行操作(例:对页面元素的增. ...

  4. 作业(更新ing)

    暴政警告 2019.4.19 1.YBT完成 7 道题目(1)广搜 3 道 (2)最短路 4 道 2.写至少 2 篇博客 (据说集中精力,一个上午/下午就能写完) 1.   一个 又一个 球细胞数目 ...

  5. java消息服务学习之JMS高级特性

    将介绍的内容是: 控制消息确认.为发送消息指定选项.创建临时目的地.使用JMS本地事务.异步发送消息 五个方面. 1.控制消息确认 在JMS消息得到确认之前,并不认为它已经成功使用.要成功使用消息,通 ...

  6. Oracle GoldenGate 18.1发布

    软件下载地址:https://www.oracle.com/technetwork/middleware/goldengate/downloads/index.html 文档下载地址: https:/ ...

  7. struts2+springmvc+hibernate开发。个人纪录

    对于很多新手来说,都不太清楚应该怎么去放置代码并让他成为一种习惯.个人的总结如下: 一.基础包类的功能 1.dao :提供底层接口 2.daoimpl:实现底层接口类,与底层交互 3.entity:实 ...

  8. [十二省联考2019]骗分过样例 luoguP5285 loj#3050

    不解释(因为蒟蒻太弱了,肝了一晚受不了了...现在省选退役,这有可能就是我做的最后一题了... #include<bits/stdc++.h> using namespace std; # ...

  9. Windows10 引导修复

    [问题]最近遇到一些用户使用的操作系统为Win10,但是使用过程中由于错误系统优化.卸载软件错误.误删系统文件.windows更新错误等,影响系统BCD引导文件,造成开机出现该BCD蓝屏报错,如下图所 ...

  10. Java程序设计第三次作业

    编写“学生”类及其测试类. 5.1 “学生”类: 类名:Student 属性:姓名.性别.年龄.学号.5门课程的成绩 方法1:在控制台输出各个属性的值. 方法2:计算平均成绩 方法3:输出各个属性的值 ...