热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java怎样使用jar包中的类_Java动态加载jar包中类的方法

JAVA启动后,经过JVM各级ClassLoader来加载各个类到内存。JVM的ClassLoader分三层,分别为BootstrapClassLoader,Exte

JAVA启动后,经过JVM各级ClassLoader来加载各个类到内存。

JVM的ClassLoader分三层,分别为Bootstrap ClassLoader,Extension ClassLoader,System ClassLoader。

Bootstrap ClassLoader是启动类加载器,它是用C++编写的,从%jre%/lib目录中加载类。

Extension ClassLoader是扩展类加载器,从%jre%/lib/ext目录加载类。

System ClassLoader,系统类加载器,它会从系统环境变量配置的classpath来查找路径。

62181e6eed96fddd2c0f366eca9b1599.png

情形一  重新jre/lib中的jar包

在windows系统上,我们可以安装多个JDK和JRE。设想一种情形: 我们设定当前JVM启动的是C:\Program Files (x86)\Java\jre1.7.0_85, 但是我们想读取在C:\Program Files (x86)\Java\jre1.8.0_60目录下\lib下deploy.jar,并通过com.sun.deploy.util.SecurityBaseline.getDeployVersion()输出当前的deployVersion。

在了解类加载机制后,我们知道lib/deploy.jar是通过启动类加载器加载的,在JVM启动后,如何去加载另一个指定目录中的deply.jar呢?

方法之一是利用写一个简单的main方法,利用命令行机制,java -cp ;C:/Program Files (x86)/Java/jre1.8.0_60/lib/deploy.jar  去加载这个main方法,具体如下

package H1;

import com.sun.deploy.util.SecurityBaseline;

public class GetDeploymentVersionMain {

public static void main(String args[]) {

System.out.println(com.sun.deploy.util.SecurityBaseline.getDeployVersion());

}

}

如何去用java调用shell命令呢?

packageH1;importjava.io.BufferedReader;importjava.io.File;importjava.io.InputStreamReader;public classTestGetDeployVersionMain{public staticString getDeployVersion(String testJREHome) {

File javaFile= new File(testJREHome, "/bin/java");

File deployJar= new File(testJREHome, "/lib/deploy.jar");

Process process= null;

String deployVersion= null;

String classpath= System.getProperty("user.dir");try{

process= Runtime.getRuntime().exec(new String[] {javaFile.getAbsolutePath(), "-cp", ";" + deployJar.getAbsolutePath()+";"+classpath+"/bin/", "H1.GetDeploymentVersionMain"});

}catch(Exception e) {throw new RuntimeException("fail to execute command");

}

System.out.println("before read deploy version...");

System.out.println("the stream is: " +process.getInputStream());try (BufferedReader in = new BufferedReader(newInputStreamReader(process.getInputStream()))) {

String line= null;while ((line = in.readLine()) != null) {

System.out.println(line);if (line.matches("^(\\d+\\.)+\\d+")) {

deployVersion=line;

}

}

System.out.println("deployVersion=" +deployVersion);returndeployVersion;

}catch(Exception e) {return "error_version";

}

}public static voidmain(String args[]) {

TestGetDeployVersionMain.getDeployVersion("c:/PROGRA~2/Java/JRE18~1.0_6");

}

}

执行结果:

c:\ws\TestProject\src>java -cp ;c:/PROGRA~2/Java/JRE18~1.0_6/lib/deploy.jar H1.TestGetDeployVersionMain

before read deploy version...

11.60.2.19

deployVersion=11.60.2.19

情形二 加载自定义类中的jar包

在程序运行的时候,如何动态加载自定义的jar包中的类呢?

步骤一 定义一个类

package com.test;

public class Utils {

public void printUtils(){

System.out.println("hello world");

}

}

使用命令jar cvf Utils.jar com/test/Utils.class 将Utils.class构建jar包

步骤二 定义加载方法

public static void loadUtilSJAR() throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException{

String class_path = "com.test.Utils";// Jar中的所需要加载的类的类名

String jar_path = "file://c:/Utils.jar";// jar所在的文件的URL

ClassLoader cl = new URLClassLoader(new URL[] { new URL(jar_path) });// 从Jar文件得到一个Class加载器

Class> c = cl.loadClass(class_path);// 从加载器中加载Class

Utils util = (Utils) c.newInstance();// 从Class中实例出一个对象

util.printUtils();

}

使用main调用这个方法,类名可以为TestDeployVersion

c:\ws\TestProject\src>java -cp ;c:/Utils.jar TestDeployVersion

hello world

方法三 使用自定义的classloader

具体可参考 http://kalanir.blogspot.jp/2010/01/how-to-write-custom-class-loader-to.html

public class JarClassLoader extends ClassLoader {

private String jarFile = "jar/test.jar"; //Path to the jar file

private Hashtable classes = new Hashtable(); //used to cache already defined classes

public JarClassLoader() {

super(JarClassLoader.class.getClassLoader()); //calls the parent class loader's constructor

}

public Class loadClass(String className) throws ClassNotFoundException {

return findClass(className);

}

public Class findClass(String className) {

byte classByte[];

Class result = null;

result = (Class) classes.get(className); //checks in cached classes

if (result != null) {

return result;

}

try {

return findSystemClass(className);

} catch (Exception e) {

}

try {

JarFile jar = new JarFile(jarFile);

JarEntry entry = jar.getJarEntry(className + ".class");

InputStream is = jar.getInputStream(entry);

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

int nextValue = is.read();

while (-1 != nextValue) {

byteStream.write(nextValue);

nextValue = is.read();

}

classByte = byteStream.toByteArray();

result = defineClass(className, classByte, 0, classByte.length, null);

classes.put(className, result);

return result;

} catch (Exception e) {

return null;

}

}

}


推荐阅读
  • Python 程序转换为 EXE 文件:详细解析 .py 脚本打包成独立可执行文件的方法与技巧
    在开发了几个简单的爬虫 Python 程序后,我决定将其封装成独立的可执行文件以便于分发和使用。为了实现这一目标,首先需要解决的是如何将 Python 脚本转换为 EXE 文件。在这个过程中,我选择了 Qt 作为 GUI 框架,因为之前对此并不熟悉,希望通过这个项目进一步学习和掌握 Qt 的基本用法。本文将详细介绍从 .py 脚本到 EXE 文件的整个过程,包括所需工具、具体步骤以及常见问题的解决方案。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • 本文介绍了如何使用Java和PDFBox库根据坐标值对PDF文件进行局部切割的方法。 ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 本文介绍如何使用 Python 的 DOM 和 SAX 方法解析 XML 文件,并通过示例展示了如何动态创建数据库表和处理大量数据的实时插入。 ... [详细]
  • 实验九:使用SharedPreferences存储简单数据
    本实验旨在帮助学生理解和掌握使用SharedPreferences存储和读取简单数据的方法,包括程序参数和用户选项。 ... [详细]
  • 字节流(InputStream和OutputStream),字节流读写文件,字节流的缓冲区,字节缓冲流
    字节流抽象类InputStream和OutputStream是字节流的顶级父类所有的字节输入流都继承自InputStream,所有的输出流都继承子OutputStreamInput ... [详细]
  • 文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke ... [详细]
  • 本文详细解析了客户端与服务器之间的交互过程,重点介绍了Socket通信机制。IP地址由32位的4个8位二进制数组成,分为网络地址和主机地址两部分。通过使用 `ipconfig /all` 命令,用户可以查看详细的IP配置信息。此外,文章还介绍了如何使用 `ping` 命令测试网络连通性,例如 `ping 127.0.0.1` 可以检测本机网络是否正常。这些技术细节对于理解网络通信的基本原理具有重要意义。 ... [详细]
  • 本文详细解析了Java类加载系统的父子委托机制。在Java程序中,.java源代码文件编译后会生成对应的.class字节码文件,这些字节码文件需要通过类加载器(ClassLoader)进行加载。ClassLoader采用双亲委派模型,确保类的加载过程既高效又安全,避免了类的重复加载和潜在的安全风险。该机制在Java虚拟机中扮演着至关重要的角色,确保了类加载的一致性和可靠性。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有