浅析类加载

前言:总结一下类加载的过程,于静态代码块、静态变量、事例变量等一些构建方式。因为这部分挺绕的,容易出错。

1、在java中可以将对象分为两大体系:字节码对象和实例对象

1.1、字节码对象:

每个类在加载(将类读到内存)时都会创建一个字节码对象,且这个对象在一个JVM内存中是唯一的.此对象中存储的是类的结构信息.所以可以说字节码对象是获取类结构信息的入口.

每个类对应的类字节码文件在jvm中都是唯一的【验证】

1     /**
2      * 测试类的字节码文件是否是唯一的
3      */
4     private static void testClassLoader_01(){
5         Class<?> class_1 = Object.class;
6         Class<?> class_2 = Object.class;
7         System.out.println(class_1 == class_2);
8         // 输出结果:true
9     }

字节码对象的获取方式?(常用方式有三种)

  • 类名.class:可以使用Class<?> 、Class<类名>来接收
  • Class.forName(“包名.类名”):编译阶段无法确定字符串对应的类名是否准确,只能用Class<?>泛型通配符来接收
  • 类的实例对象.getClass()
 1     /**
 2      * 三种类加载方式
 3      */
 4     private static void testClassLoader_02() throws ClassNotFoundException {
 5         Class<?> class_1 = Object.class;
 6         Class<?> class_2 = Class.forName("java.lang.Object");
 7         Class<?> class_3 = new Object().getClass();
 8         System.out.println((class_1 == class_2)&&(class_2 == class_3));
 9         // 注意:三种类加载方式,加载的是同一个类字节码文件
10     }

类加载时:

  静态代码块:可以执行,但不一定会执行。

  静类变量:可以初始化,但不一定会初始化。

1 class C_Object{
2     static{
3         System.out.println("进入了静态代码块");
4     }
5 }

  

1     private static void testClassLoader_03() throws ClassNotFoundException {
2         // 这个不会输出 进入了静态代码块
3         Class<?> class_1 = Object.class;
4         // 这个会输出  进入了静态代码块
5         Class<?> class_2 = Class.forName("com.turtle.oop.C_Object");
6     }

  

 对Class.forName()进行剖析:

  

1      // arg1:这个是我们要加载的字节码类
2         // arg2:这个是确定我们在类加载的时候是否执行静态代码块,默认是true,执行,如果为false就不会执行静态代码块
3         // arg3:使用类加载器来完成类的加载
4         Class<?> c3 = Class.forName("com.turtle.oop.ClassObject",true,Thread.currentThread().getContextClassLoader());

总结案例:

 1 package com.turtle.oop;
 2
 3 import java.util.HashMap;
 4 import java.util.Map;
 5
 6 public class Test_ClassLoader_02 {
 7     public static void main(String [] args) throws ClassNotFoundException {
 8         Class<?> class_01 = Class.forName("com.turtle.oop.C_Object_2",true,Thread.currentThread().getContextClassLoader());
 9         // 出错
10     }
11 }
12 class C_Object_2{
13 /*    为类中的静态变量赋值是按顺序下来的
14     1-加载ClassObject_03类到内存中
15     2-为ClassObject_03类型的变量instance赋值,会调用构造方法
16     3-构造方法中使用了静态变量map,但是此时的静态变量map还没有赋值*/
17     static C_Object_2 instance=new C_Object_2();
18     // 如果和上面的交换位置也就不会出错了、如果改为非静态的就不会出错了
19     static Map<String,String> map = new HashMap<>();
20     public C_Object_2(){
21         map.put("Key_01","Value_01");
22     }
23 }

 报错:空指针错误

D:\Programs\JDK8\bin\java.exe "-javaagent:D:\Programs\JetBrains\IntelliJ IDEA 2018.3.5\lib\idea_rt.jar=55074:D:\Programs\JetBrains\IntelliJ IDEA 2018.3.5\bin" -Dfile.encoding=UTF-8 -classpath D:\Programs\JDK8\jre\lib\charsets.jar;D:\Programs\JDK8\jre\lib\deploy.jar;D:\Programs\JDK8\jre\lib\ext\access-bridge-64.jar;D:\Programs\JDK8\jre\lib\ext\cldrdata.jar;D:\Programs\JDK8\jre\lib\ext\dnsns.jar;D:\Programs\JDK8\jre\lib\ext\jaccess.jar;D:\Programs\JDK8\jre\lib\ext\jfxrt.jar;D:\Programs\JDK8\jre\lib\ext\localedata.jar;D:\Programs\JDK8\jre\lib\ext\nashorn.jar;D:\Programs\JDK8\jre\lib\ext\sunec.jar;D:\Programs\JDK8\jre\lib\ext\sunjce_provider.jar;D:\Programs\JDK8\jre\lib\ext\sunmscapi.jar;D:\Programs\JDK8\jre\lib\ext\sunpkcs11.jar;D:\Programs\JDK8\jre\lib\ext\zipfs.jar;D:\Programs\JDK8\jre\lib\javaws.jar;D:\Programs\JDK8\jre\lib\jce.jar;D:\Programs\JDK8\jre\lib\jfr.jar;D:\Programs\JDK8\jre\lib\jfxswt.jar;D:\Programs\JDK8\jre\lib\jsse.jar;D:\Programs\JDK8\jre\lib\management-agent.jar;D:\Programs\JDK8\jre\lib\plugin.jar;D:\Programs\JDK8\jre\lib\resources.jar;D:\Programs\JDK8\jre\lib\rt.jar;D:\Project\HomeWorks_FrameWork\01-JavaEE-Heighten\javaee\target\classes com.turtle.oop.Test_ClassLoader_02
Exception in thread "main" java.lang.ExceptionInInitializerError
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:348)
    at com.turtle.oop.Test_ClassLoader_02.main(Test_ClassLoader_02.java:8)
Caused by: java.lang.NullPointerException
    at com.turtle.oop.C_Object_2.<init>(Test_ClassLoader_02.java:15)
    at com.turtle.oop.C_Object_2.<clinit>(Test_ClassLoader_02.java:12)
    ... 3 more

Process finished with exit code 1

 

原文地址:https://www.cnblogs.com/zhh19981104/p/10740348.html

时间: 2025-01-01 00:28:11

浅析类加载的相关文章

浅析java基本程序

1.包 package package语法:包名.类名 ;包名的写法规范:所有字母需小写. 当然也可以采用静态导入  例如 import static java.lang.Math.* 有包的对象不能使用默认包的对象. import java.lang  包是java虚拟机自动导入的包,在使用java.lang包时我们可以不需要导包:例如:Thread类,Exception类,System类,String类等,可以相应的查看Api. java.util.*  这里的*表示java.util下的所

浅析java类加载器ClassLoader

作为一枚java猿,了解类加载器是有必要的,无论是针对面试还是自我学习. 本文从JDK提供的ClassLoader.委托模型以及如何编写自定义的ClassLoader三方面对ClassLoader做一个简要的总结. JDK中提供的ClassLoader 1. Bootstrap ClassLoader Bootstrap加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib以及%JAVA_HOME%/jre/classes中的类,是最顶

[Java类加载器]Java中classLoader浅析.

本文为在公司内部TD上写的一篇小文, 主要讲解java中classLoader基础知识, 现在拿来这里分享一下. 一.问题 请在Eclipse中新建如下类,并运行它: 1 package java.lang; 2 3 public class Long { 4 public static void main(String[] args) { 5 System.out.println("Hi, i am here"); 6 } 7 } 你能猜到它的运行如果吗? 不错,就是如下这个样子!

OpenJDK类加载实现浅析#2:安全检查

今天来看下类加载过程中的一些安全检查.在那之前得先来了解下Java的Access Control. Access Control The access control architecture in the Java platform protects access to sensitive resources (for example, local files) or sensitive application code (for example, methods in a class). A

OpenJDK类加载实现浅析#3:并行加载

今天来看下OpenJDK类加载中关于并行加载的一些代码.还是一样要分别看看类加载库跟虚拟机,因为二者在这方面仍然是需要配合完成的. 类加载库所做的工作 在JDK7之前,ClassLoader#loadClass方法是synchronized的, protected synchronized Class<?> loadClass(String name, boolean resolve) 也就是说,类加载的时候,直接是要锁住整个classloader的. 到了JDK7,这个地方终于做出了优化,直

健康,home? [java的内存浅析]

健康,home? [java的内存浅析] 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 乐观上上,how can other kno u,u r yourself!I must be strong and carry on. -泥沙砖瓦浆木匠 一.闲谈下 201407月记着那时候身体垮了下来,呵呵.想说,对自己的说,也是对大家的负责吧.那时候胸疼胸闷,然后几乎累垮了,我还坚持了一星期,那一星期真的迷迷糊糊.完全不能

Java内存分配全面浅析

进入正题前首先要知道的是Java程序运行在JVM(Java  Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性.所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提.          简单通俗的讲,一个完整的Java程序运行过程会涉及以下内存区域: l  寄存器:JVM内部虚拟寄存器,存取速度非常快,程序不可控制. l  栈:保存

Java 内存分配全面浅析

本文将由浅入深详细介绍Java内存分配的原理,以帮助新手更轻松的学习Java.这类文章网上有很多,但大多比较零碎.本文从认知过程角度出发,将带给读者一个系统的介绍. 进入正题前首先要知道的是Java程序运行在JVM(Java Virtual Machine,Java虚拟机)上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性.所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提. 简

java语言安全机制浅析

java通过所谓的沙箱安全模型保证了其安全性,下面我们就来看看java提供的安全沙箱机制. 组成沙箱的基本组件如下: 1.类装载器结构: 2.class文件检验器: 3.内置于java虚拟机(及语言)的安全特性: 4.安全管理器及java API. 一.类装载器体系结构 1.防止恶意代码去干涉善意的代码. 这是通过为不同类加载器提供不同的命名空间来实现的,在java虚拟机中,在同一个命名空间内的类可以直接进行交互,而不同的命名空间中类甚至不能觉察彼此的存在,除非显式地提供允许它们交互的机制. 2