Java中动态加载class机制实验

Java中的ClassLoader 动态加载机制 前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块。 当然这里要说的并不是android中的动态加载机制,而是java中的ClassLoader动态加载我们的class,虽然android是基于Dalvik,但是先了解java中JVM怎么来加载我们的clas 阅读详情
Java的一个强大的特性是能够动态加载一个给定名称的类,而事先不需要指导这个类的名字。这个特性使得Java的开发人员能够构造一个不需要重新编译即可扩展和修改的灵活动态的系统,在Java中,动态加载通常是调用类java.lang.Class的forName方法来实现;然而,在一个jar包中调用Class.forName会出现一些奇怪的错误。

  下面的内容需要读者具备一定的java知识、ClassLoader知识、编译原理和面向对象的知识。
问题描述:
例如,下面的代码在Main方法中调用ClassLoader来加载一个命令行传入的class.
LoaderTest.java文件
package aa
public class LoaderTest
{
public static void main(String[] args)
{
LoadClass(args[0]);
}

public static void LoadClass(String clsName)
{
try
{
beLoaded bl = 
(beLoaded)Class.forName(clsName).newInstance();
bl.PrintInfo();
}
catch (Exception e)
{
e.printStackTrace();
}

}
}

beLoaded.java文件
package aa;
public class beLoaded
{
public void PrintInfo()
{
System.out.println("I am be loaded!");
}
}

  上面的代码在正常情况下非常好使,并且使得整个系统可以同具体的java类分离开来,只需要传入一个class的类名即可完成功能调用。而且从扩展的角度来说,定义一些从beLoaded类上继承下来的类,并将类名通过参数传入系统,即可实现各种不同的功能类的调用,非常方便。
在命令行上键入如下命令:
> java aa.LoaderTest aa.beLoaded
屏幕会输出下面的内容:
I am be loaded!

下面我们创建一个beLoaded的子类,类名叫做beLoadedChild,代码如下:
package aa;

public class beLoadedChild extends beLoaded
{
public void PrintInfo()
{
System.out.println("I am be loaded and I am Child");
}
}
在命令行上键入如下命令:
> java aa.LoaderTest aa.beLoadedChild
屏幕会输出下面的内容:
I am be loaded and I am Child

  通过上面的例子我们可以看出,只要设计好LoaderTest这个类和beLoaded类,就可以实现系统的扩展性,对不同的功能目标调用不同的beLoaded的子类,来完成不同的应用,系统十分的灵活和方便。

  在Java中,为了更好的管理Java的Class,Java允许开发者将一些相关的Class打包放到.jar文件中去,使得系统管理非常的方便,因此我们将上面的aa.LoaderTest和aa.beLoaded这两个类打包到aa.jar中去。将.jar文件放到JAVA_HOME/jre/lib/ext目录中去。
  因为beLoadedChild是子类,所以我们将这个类放在外面,可以随时地修改这个子类而不用重新编译LoaderTest两个类。这里我们将beLoadedClass.class放在当前目录下的aa目录下,具体方法如下:
> java aa.LoaderTest aa.beLoaded
屏幕会输出下面的内容:
I am be loaded!

  上面的beLoaded类在.jar包中存在,所以执行起来没有问题,我们看一看下面的执行情况:
> java aa.LoaderTest aa.beLoadedChild
屏幕会输出下面的内容:
java.lang.ClassNotFoundException: aa.beLoadedChild
at java.net.URLClassLoader$1.run(URLClassLoader.java:199)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:187)
at java.lang.ClassLoader.loadClass(ClassLoader.java:289)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:274)
at java.lang.ClassLoader.loadClass(ClassLoader.java:235)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:302)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at aa.LoaderTest.LoadClass(LoaderTest.java:25)
at aa.LoaderTest.main(LoaderTest.java:18)


  系统提示找不到aa.beLoadedChild这个类,可是这是不应该出现的问题,因为beLoadedChild类就在当前目录的aa目录下中,从package的角度来讲是没有问题的,但是问题出在什么地方呢?
问题分析
  分析这个问题,我们可以从两个方面入手,一个是.jar的问题,另一个是java虚拟机的加载机制问题,这两方面最终会统一到java的加载机制问题。
  为什么说是.jar的问题呢?首先从运行情况的比较来看,在所有的类都不在.jar文件中时,程序执行没有问题,在打包以后,执行.jar文件中包含的class没有问题,而.jar文件之外的class就出现了ClassNotFound的错误,通过这个现象我们可以认为问题是由.jar打包而产生的。
  但是反过来,sun公司提供的jdk都是以.jar的形式发放的,他们的.jar包中肯定也会存在动态加载class的问题,比较典型的是jdbc,在使用jdbc时都要使用Class.forName()来加载数据库的驱动,为什么这时没有出现问题呢?
  所以上面的问题表明sun公司的jar包中在动态加载类时肯定进行了特殊的处理或者调用,才使得加载jdbc驱动没有产生ClassNotFound的错误。
  看来问题的根源还是在java虚拟机的加载机制上了。
  为了理解这个问题,你需要理解一些Java ClassLoader模型的基础知识以及JDK1.1同Java2之间的差别。
  Java2 ClassLoader Delegation Model.(Java2 ClassLoader委托模型)
Java2 ClassLoader模型是一种“delegating parent(委托给父ClassLoader)”模型,这意味着当一个ClassLoader被要求加载一个class时,它首先要求它的parent ClassLoader来加载这个类。只有当它的parent 没有加载过这个类并且也不能加载这个类时,它才自己处理这个加载请求。这就是说ClassLoader是一个类似于树的形式的结构,”bootstrap”这个ClassLoader是这棵树的根节点。
  任何一个用户创建的ClassLoader必须拥有一个parent ClassLoader,如果创建时没有提供parent,ClassLoader的创建者假定其parent 是”system”或者ClassLoader。
  在JVM中被加载的每一个Class都会同加载它的ClassLoader保持有隐含的关联,这个关联我们可以通过Class的方法getClassLoader来找到。每一个Class同一个并且只能是一个ClassLoader相关联,并且这个关联不能通过改变ClassLoader的引用来指向另一个ClassLoader。
  通常程序员会直接调用ClassLoder的loadClass方法,JVM通常是隐式的调用该方法。在JDK1.0和1.1模型中,ClassLoader直接覆盖了loadClass方法来负责实现该方法。而在JDK1.2中,loadClass方法调用它的parent的loadClass方法来检查其parent 是否已经加载了class,只有当它的parent加载class失败时,它自己才有机会加载class.
  通过上面的分析我们可以大致的猜测到,直接通过Class.forName来动态加载class,如果该调用在.jar中的话,那么它的加载范围就在整个.jar中,而不是整个java虚拟机的classpath中。根据java的ClassLoader的工作原理我们可以知道,java的ClassLoader是一个继承的过程,整个java虚拟机拥有一个classloader,而其下的每一个.jar文件应该对应一个ClassLoader,这个ClassLoader的加载范围就是整个.jar文件中的范围,所以前面我们做的例子中当加载.jar文件中的class时,就可以正常通过并执行,而加载.jar之外的class时,由于ClassLoader的范围中没有这个class,所以产生ClassNotFound的错误。
  为了证实我们上面所做的猜测,我们来做一个程序试验一下:
  前面说到java的ClassLoader是以一个树的形式存在的,通过这个特点我们可以考虑在加载class时不使用当前类的ClassLoader,而是使用整个应用程序的ClassLoader,也就是树的根节点来加载类,这样肯定就没有问题了;或者我们不用根节点,使用当前类的ClassLoader的parent ClassLoader也许也同样能够解决问题;再或者我们使用当前进程或者线程的ClassLoader也应该能够解决这个问题。


解决方法:
  下面我们来做个试验,将LoaderTest中的方法修改一下,使用当前线程的ClassLoader来加载class,看看是否能够成功,代码如下:
package aa;
public class LoaderTest
{
public static void main(String[] args)
{
LoadClassEx(args[0]);
}
public static void LoadClass(String clsName)
{
try
{
beLoaded bl = 
(beLoaded)Class.forName(clsName).newInstance();
bl.PrintInfo();
}
catch (Exception e)
{
e.printStackTrace();
}

}

public static void LoadClassEx(String clsName)
{
try
{
Thread t = Thread.currentThread();
ClassLoader cl = t.getContextClassLoader();
beLoaded bl = (beLoaded)cl.loadClass(clsName).newInstance();
bl.PrintInfo();
}
catch (Exception e)
{
e.printStackTrace();
}

}
}
编译后,打包,并将.jar文件放入到运行目录中去,然后在命令行输入下列命令:
> java aa.LoaderTest aa.beLoaded
屏幕会输出下面的内容:
I am be loaded!

继续输入下列命令:
> java aa.LoaderTest aa.beLoadedChild
屏幕会输出下面的内容:
I am be loaded and I am Child

  这样我们的猜测和运行结果完全一致,在.jar包中的class拥有了加载任意位置的class文件的能力了。

  我们还可以使用ClassLoader cl = ClassLoader.getSystemClassLoader();来获得系统级的ClassLoader,以获得更广泛的加载范围。
Springboot基于Java动态编译实现项目动态加载class文件 在IDE中运行springboot 程序 类加载器是JDK自带的,类加载器已经完成了依赖jar的加载,所以编译是没问题的,但是springboot 用的是springboot自己写的LaunchedURLClassLoader。因为技术都是为业务服务的,所有的功能开发出来都需要有他的用途;-------------------------------------------------------正确写法分割线------------------------------------------------ 阅读详情

相关推荐

Java类动态加载(一)——java源文件动态编译为class文件

NULL 博文链接:https://zheng12tian.iteye.com/blog/1488813

在Java中动态加载class

   Java的一个强大的特性是能够动态加载一个给定名称的类,而事先不需要指导这个类的名字。这个特性使得Java的开发人员能够构造一个不需要重新编译即可扩展和修改的灵活动态的系统,在Java中,动态加载通常是调用类java.lang.Class的forName方法来实现;然而,在一个jar包中调用Class.forName会出现一些奇怪的错误。  下面的内容需要读者具备一定的java知识、Cl

碧海蓝天 9708

Java 动态加载jar和class文件实例解析

主要介绍了Java 动态加载jar和class文件实例解析,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下

【Java JVM】Class 文件的加载

Java 虚拟机把描述类的数据从 Class 文件加载到内存, 并对数据进行校验, 转换解析和初始化, 最终形成可以被虚拟机直接使用的 Java 类型,这个过程被称作虚拟机的。与那些在编译时需要进行连接的语言不同, 在 Java 语言里面, 类的加载, 连接和初始化过程都是在程序运行期间完成的, 这种策略让 Java 语言进行提前编译会面临额外的困难,

LCN29的博客 1822

[ESP32]:基于esp-modbus实现serial主机

[ESP32]:基于esp-modbus实现serial主机

LINKKEEE的博客 2567

【影像组学】用3Dslicer或Python提取影像组学特征

用3Dslicer或Python提取影像组学特征

abdslfwoeugp 1万+

java(Class 常用方法 获取Class对象六种方式 动态和静态加载 类加载流程)

java学习笔记

m0_62434717的博客 3734

GEE|基于时间序列特征的山东省玉米随机森林分类代码

主题思路: 本实验为二分类实验,分类目标包括:玉米、其他(建筑、水体、水稻、 裸地、森林、小麦、道路、大蒜等),采用人工设计的特征指数的时间序列特征为分类依据,选取分类器为:随机森林分类器,并选取样本集中 70%作为训练样本,30%作为测试样本,通过调整随机森林棵数,调整分类器结构。选取以下参数进行分类: ⚫ 时间尺度:1990 年 4 月 15 日 - 1990 年 9 月 30 日 ⚫ 空间尺度:山东省 ⚫ 影像融合时间间隔:16天 ⚫ 特征值选择:['nir','ndvi'...

weixin_46493028的博客 7466

java 静态 动态加载_java 静态代码块 动态代码块 加载时间

//自己看了一些视频,察觉了一些问题 现在来说明:Java中静态代码块 动态代码块加载时间// 像JVM传递参数-verbose:class 我们可以看到classload加载class的顺序①证明证明Java是动态加载类的 ②动态块,静态块 加载顺序public class Hello {public static void main(String[] args) {// TODO Auto...

weixin_30895059的博客 276

海康visionmaster-渲染结果:通过绑定流程或模块获取 渲染结果的方法

海康visionmaster-渲染结果:通过绑定流程或模块获取 渲染结果的方法

视觉人机器视觉的博客 2636

【论文精读】Graph WaveNet-深度时空图模型

Graph WaveNet构建了一个自适应邻接矩阵,它能保留隐藏的空间依赖关系,能够自动从数据中发现未见的图结构。提出了一个有效且高效的框架,可同时捕捉空间和时间依赖关系。其核心思想是将其提出的图卷积与扩张因果卷积相结合,使每个图卷积层都能处理空间依赖关系。在交通数据集上评估了提出的模型,并以较低的计算成本获得了最先进的结果。

打酱油的葫芦娃 1007

【JVM】JVM加载class文件的原理机制

一、JVM简介 JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 Java语言的一个非常重要的特点就是与平台的 无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,J...

renjingjingya0429的博客 2万+

Codex 接入国产大模型完整指南:CC-Switch 与 Codex++ 的工程化选型

Codex 默认走 OpenAI Responses API,而 DeepSeek、GLM、Kimi 等国产模型只提供 OpenAI-compatible 的 Chat Completions——两套协议在消息结构、流式响应、reasoning 字段、tool call 上都不兼容,所以"改个 Base URL + 填国产 Key"这种朴素操作根本跑不通。本文从架构师视角出发,把 Codex 接入国产大模型这件事讲透:先剖析协议链路到底卡在哪,再对比 CC-Switch和 Codex++两套主流方案的差异

少说,多做 3845

[JAVA]动态重新加载Class机制

[b]Java动态重新加载Class[/b] 项目中使用到了动态重新加载Class的机制,作用是让一些代码上线之前可以在线上环境测试一下,当然,这是非常不好的测试机制,我刚来的时候也为这种机制感到惊讶—怎么可以在线上环境运行测试代码!后来经过了解,这么做的原因有以下两个: [list] [*]有些代码没有办法在本地进行测试,本地没有线上的环境 [*]我们弱到连测试机都没有(这是...

My Tech Disk 734

Unity 编辑器篇|(四)编辑器拓展GUI类 (全面总结 | 建议收藏)

GUI 类是 Unity GUI 的接口,并且具有手动定位功能。“即时模式”GUI 系统(也称为 IMGUI)是一个完全独立的功能系统,不同于 Unity 基于游戏对象的主 UI 系统。IMGUI 是一个代码驱动的 GUI 系统,主要用作程序员的工具。为了驱动该系统,需在实现脚本上调用 OnGUI 函数即时模式 GUI 系统常用于:创建游戏内调试显示和工具。为脚本组件创建自定义检视面板。创建新的编辑器窗口和工具以扩展 Unity 本身。

游戏开发小Y的博客 12万+

【测开求职】面试题:数据结构 吐血整理

本篇文章是笔者为准备研究生复试以及校招而写,因此主要针对问答,注重理解,而不在于细节计算。涵盖考研范围内的所有知识内容,读者可以先查看上面的链接走一遍数据结构的整体框架结构。其中,重点难点以及易混淆的知识点,笔者用其他近30篇文章进行了详述,在知识点处贴好了链接,有需要的可以查阅。

vector的博客 7064

Class 文件和类加载机制

Java 源码(.java)经过javac 编译器编译生成的字节码文件(.class由 JVM 识别执行,包含类的完整结构信息(如字段、方法、常量池、访问权限等);是平台无关的中间代码。JVM 的操作对象是 Class 文件,JVM 把 Class 文件中描述类的数据结构加载到内存中,并对数据进行校验、解析和初始化,最终形成可以被 JVM 直接使用的类型,这个过程被称为类加载机制。其中最重要的三个概念就是:类加载器、类加载过程和类加载器的双亲委派模型。类加载器。

m0_73748193的博客 1640

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

java如何加载class文件

java文件的类加载机制: jvm将描述类的数据从class文件加载到内存,然后对数据进行校验,解析以及初始化,在java虚拟机中形成可以直接使用的java类型。 java类文件的加载是动态的。 java为我们提供了2种类文件加载的动态机制。 1.隐式加载---- new一个对象+调用一个类的静态方法 2.显示加载----(1)java.lang.Class的forName方法加载 ...

sinat_24041961的博客 4587

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

JAVA反射与类加载机制

JAVA反射与类加载机制JAVA反射动态语言反射机制反射的应用场合JAVA反射API反射使用步骤获取Class对象通过反射创建对象JVM类加载机制类加载的声明周期类加载器双亲委派模型 JAVA反射 动态语言 动态语言:程序在运行时可以改变结构,新的函数可以引进,已有的函数可以被删除等结构上的变化。 从反射角度说JAVA属于半动态语言。 反射机制 java反射机制:在运行状态下,对任意一个类都...

lym3lavender的博客 3702

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java中class文件的动态加载

动态加载class文件,使用自定义加载器或者URLClassLoader,如下。 假如想加载G:\\temp下的Model.class,则 URLClassLoader loader=new URLClassLoader(new URL[]{new URL("file:G:\\temp\\")}); Object model=loader.loadClass("Model").newI

Hectorhua的专栏 4259

JVM加载class文件的原理机制简单总结

JVM加载class文件的原理机制

weisg81的专栏 1万+

java动态加载机制_java动态加载机制

假设有一个class,ClassLoader首先把它load到内存里的code segment(内存里存放代码段的),站在ClassLoader的角度,内存里的一个一个的class就是一个一个的对象,这个对象就是xx.class,实际就是Class类的对象。Load完class,找到main函数开始执行,然后会把很多其他的类Load进来,动态加载机制。测试动态加载机制:新建项目Reflection...

weixin_39798497的博客 252

Java反射机制:从Class对象到动态编程

class也是类,因此也继承Object类class类对象不是new出来的,是系统创建的对于某个类的class类对象,在内存中只有一份,因为类只加载一次每个类的实例都会记得自己是由哪个class实例所生成通过class可以完整的得到一个类的完整结构,通过一系列apiclass对象是存放在堆的类的字节码二进制数据放在方法区,或称为类的元数据。

k942649453的博客 942

java 加载jar_Java 动态加载jar和class文件实例解析

本文研究的主要是Java 动态加载jar和class文件的相关内容,具体如下。JAVA中类文件加载是动态的。也就是说当我们用到的时候才会去加载,如果不用的话,就不会去加载我们的类。JAVA为我们提供了两种动态机制。第一种是隐式机制。第二种是显示机制。如下:两种方法:隐式机制 :new一个对象 + 调用类的静态方法显式机制 :由 java.lang.Class的forName()方法加载由 java...

weixin_42511201的博客 803

java 动态重新加载class_动态重新加载Class机制之代码测试

package com.ailk;import java.io.*;/*CompilingClassLoader动态的编译Java源文件。它检查.class文件是否存在,.class文件是否比源文件陈旧。*/public class CompilingClassLoader extends ClassLoader {protected void finalize(){System.out.prin...

weixin_32290249的博客 605

反射、 Class类、JVM的类加载机制、Class的常用方法

反射、 Class类、JVM的类加载机制、Class的常用方法

hutao8896的博客 1190
上一篇: Google后Hadoop时代的新“三驾马车”——Caffeine、Pregel、Dremel
下一篇: 移动医疗开源方案
Ice008
博客等级 码龄19年 34粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值