定义需要加载的类

为了能够实现类加载,并展示效果,定义一个Hello类,再为其定义一个sayHello()方法,加载Hello类之后,调用它的sayHello()方法。

public class Hello {public static void sayHello(){System.out.println("Hello,I am ....");}
}

定义类加载器

自定义加载器,需要继承ClassLoader,并重写里面的protected Class findClass(String name) throws ClassNotFoundException方法。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;public class MyClassLoader extends ClassLoader {/*** 重写父类方法,返回一个Class对象* ClassLoader中对于这个方法的注释是:* This method should be overridden by class loader implementations*/protected Class<?> findClass(String name) throws ClassNotFoundException {Class clazz = null;String classFilename = name + ".class";File classFile = new File(classFilename);if (classFile.exists()) {try (FileChannel fileChannel = new FileInputStream(classFile).getChannel();) {MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, 0, fileChannel.size());byte[] b = mappedByteBuffer.array();clazz = defineClass(name, b, 0, b.length);} catch (IOException e) {e.printStackTrace();}}if (clazz == null) {throw new ClassNotFoundException(name);}return clazz;}public static void main(String[] args) throws Exception{MyClassLoader myClassLoader = new MyClassLoader();Class clazz = myClassLoader.loadClass(args[0]);Method sayHello = clazz.getMethod("sayHello");sayHello.invoke(null, null);}
}

编译需要加载的类文件

类加载的时候加载的是字节码文件,所以需要预先把定义的Hello类编译成字节友文件。

javac Hello.java

验证字节码文件是否编译成功,利用二进制文件查看器查看我们编译之后的文件,样式如下:

0000000 177312 137272 000000 032000 016000 000012 000006 004416
0000020 007400 010000 000010 005021 011000 011400 000007 003424
0000040 012400 000001 036006 067151 072151 000476 001400 024450
0000060 000526 002000 067503 062544 000001 046017 067151 047145
0000100 066565 062542 052162 061141 062554 000001 071410 074541
0000120 062510 066154 000557 005000 067523 071165 062543 064506
0000140 062554 000001 044012 066145 067554 065056 073141 006141
0000160 003400 004000 000007 006026 013400 014000 000001 044017
0000200 066145 067554 044454 060440 020155 027056 027056 000007
0000220 006031 015000 015400 000001 044005 066145 067554 000001
0000240 065020 073141 027541 060554 063556 047457 065142 061545
0000260 000564 010000 060552 060566 066057 067141 027547 074523
0000300 072163 066545 000001 067403 072165 000001 046025 060552
0000320 060566 064457 027557 071120 067151 051564 071164 060545
0000340 035555 000001 065023 073141 027541 067551 050057 064562
0000360 072156 072123 062562 066541 000001 070007 064562 072156
0000400 067154 000001 024025 065114 073141 027541 060554 063556
0000420 051457 071164 067151 035547 053051 020400 002400 003000
0000440 000000 000000 001000 000400 003400 004000 000400 004400
0000460 000000 016400 000400 000400 000000 002400 133452 000400
0000500 000261 000000 000001 000012 000000 000006 000001 000000
0000520 000002 000011 000013 000010 000001 000011 000000 000045
0000540 000002 000000 000000 131011 001000 001422 000266 130404
0000560 000000 000400 005000 000000 005000 001000 000000 002000
0000600 004000 002400 000400 006000 000000 001000 006400
0000616

编译自定义的类加载器并执行程序

//编译代码
javac MyClassLoader.java
//当然我们也可以同时编译我们所有的java源文件
javac *.java

执行成功之后,我们用下面的语句执行代码,测试是否成功,并查看结果

java MyClassLoader Hello
//运行结果
Hello,I am ....

当程序按照预期显示,就证明我的自定义类加载器成功了。

总结

通过上面的程序代码,简单的实现JVM的类加载过程,知道了程序运行的一点流程。但是在编写的时候有如下坑需要注意

  • 类文件不需要指定包,否则加载的时候我们需要额外的处理,把包中的"."替换成文件系统的路径"/"。

  • 需要加载的Hello类中的反射调用的方法要用static修饰,这样invoke的时候第一个参数才可以使用null关键字代替,否则需要创建一个对应的类实例。
    官方文档中有这样一句话If the underlying method is static, then the specified obj argument is ignored. It may be null.

Java 自定义 ClassLoader 实现 JVM 类加载相关推荐

  1. 【java虚拟机系列】JVM类加载器与ClassNotFoundException和NoClassDefFoundError

    在我们日常的项目开发中,会经常碰到ClassNotFoundException和NoClassDefFoundError这两种异常,对于经验足够的工程师而言,可能很轻松的就可以解决,但是却不一定明白为 ...

  2. 【Java虚拟机规范】JVM类加载机制

    [Java虚拟机规范]JVM类加载机制 理论知识 一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载(Loading).验证(Verification).准备(Prep ...

  3. 【深入Java虚拟机】之四:类加载机制

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17881581 类加载过程     类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个 ...

  4. JVM 类加载机制与加载过程

    JVM的类加载机制:在代码编译后,就会生成JVM(Java虚拟机)能够识别的二进制字节流文件(*.class).而JVM把Class文件中的类描述数据从文件加载到内存,并对数据进行校验.转换解析.初始 ...

  5. Java 工程师必须掌握的 JVM 类加载机制!

    这篇文章不聊别的,专门来侃侃JVM的类加载机制 概念 类加载器把class文件中的二进制数据读入到内存中,存放在方法区,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据 ...

  6. 《Java虚拟机原理图解》5. JVM类加载器机制与类加载过程

    参考网址:http://blog.csdn.net/luanlouis/article/details/50529868 0.前言 读完本文,你将了解到: 一.为什么说Jabalpur语言是跨平台的 ...

  7. Java Se:自定义ClassLoader

    JVM是如何知道java.lang包中的类的?JVM又是如何知道我们应用中的类的?我们的应用中明明是有某个类, 但是JVM却抛出ClassNotFoundException,这是为什么?XxxImpl ...

  8. 深入理解Java虚拟机——JVM类加载机制(类加载过程和类加载器)

    一.什么是类加载机制? 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 二.类加载的时机 类 ...

  9. JVM类加载机制(ClassLoader)源码解析

    http://blog.csdn.net/chenyi8888/article/details/7066569 其实JVM类加载机制,简单地说就是类管理,也就是我们生成的class文件. 三个步骤:装 ...

最新文章

  1. 神经网络中参数量parameters和FLOPs计算
  2. Bitmap与IplImage之间的转换
  3. android开源2016_出版商的选择:2016年顶级开源书籍
  4. 洛谷 P4823 [TJOI2013]拯救小矮人
  5. 战争论 —— 蓝田之战
  6. 日常推荐大神操作,如何再oracle中delete数据后恢复
  7. [BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)
  8. 关于AMS1117-ADJ 电压调节计算
  9. 软件升级 防火墙 飞塔_FortiGate软件版本升级
  10. 接口调用一会正常,一会失败
  11. OpenGL 加载DDS文件(压缩纹理)
  12. OA(二)编写基本的CURD
  13. Futaba M11BT222A VFD(主控PT6311)STC51单片机驱动程序
  14. python之路day3_python之路:day3
  15. 爬虫--智联爬取--拼接链接的演示
  16. 企业微信海外版此前将名称改为 “Wecom”,腾讯打算将其设置为微信的潜在替代方案
  17. 批处理 检测U盘插入并自动备份文件
  18. 培智儿童的计算机教育,特殊教育学校计算机信息技术教学的几点做法
  19. 基于STM32的智能车/平衡小车/蓝牙小车
  20. 钉钉群机器人消息通知

热门文章

  1. 查看.net frameword版本
  2. JS编程建议——42:用好正则表达式静态值
  3. Docker 1.10版本发布
  4. 用友互联网战略的变与不变
  5. 微服务架构之外的选择——基于服务架构
  6. 简单的XML和JSON数据的处理
  7. POJ 2286 The Rotation Game IDA*
  8. C# 使用正则表达式去掉字符串中的数字,或者去掉字符串中的非数字
  9. A Data Access Layer to persist business objects using attributes and reflection - Part II [无常译]...
  10. 使用Matlab求解定积分/不定积分