热门标签 | 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;

}

}

}


推荐阅读
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • 基于SpringBoot打造在线教育系统(6)– 二级分类模块UI篇
    这一节来做二级分类,为了快速开发,一级分类只做新增,暂时不考虑修改和删除,如果一定要删,就去数据库删吧。我们接下来,需要通过一级分类,获取所有的二级分类。开始 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
  • 面向对象之3:封装的总结及实现方法
    本文总结了面向对象中封装的概念和好处,以及在Java中如何实现封装。封装是将过程和数据用一个外壳隐藏起来,只能通过提供的接口进行访问。适当的封装可以提高程序的理解性和维护性,增强程序的安全性。在Java中,封装可以通过将属性私有化并使用权限修饰符来实现,同时可以通过方法来访问属性并加入限制条件。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文整理了Java中org.gwtbootstrap3.client.ui.Icon.addDomHandler()方法的一些代码示例,展示了Icon.ad ... [详细]
  • ElasticSearch成功安装完毕。 测试数据添加出现{  error:{    root_cause ... [详细]
  • systemd-nspawn可以创建最轻量级的容器(ns的意思就是namespace),本文的实验平台是Ubuntu16.04,x86_64机器。本文的目的是:在Ubuntu中用syst ... [详细]
  • 生产环境下JVM调优参数的设置实例
     正文前先来一波福利推荐: 福利一:百万年薪架构师视频,该视频可以学到很多东西,是本人花钱买的VIP课程,学习消化了一年,为了支持一下女朋友公众号也方便大家学习,共享给大家。福利二 ... [详细]
  • Android系统启动过程分析一、Android平台架构首先贴一张Android系统架构图方便理解整个Android架构,这可以让我们从整体上对整个启动流程有个大概认知。可以看出整 ... [详细]
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社区 版权所有