1
加载某一根目录下的class文件(此处代码转载)
public class TestClassLoader extends ClassLoader{
private static final int CAPACITY = 1024;
private String baseClassName;//根目录路径,例如某一个工程的classes目录
public TestClassLoader(String baseClassName) {
if (!baseClassName.endsWith(File.separator)) {
this.baseClassName = baseClassName + File.separator;
} else {
this.baseClassName = baseClassName;
}
}
protected Class<?> findClass(final String name) throws ClassNotFoundException {
byte[] b = this.getByteFromClass(name);
return this.defineClass(name, b, 0, b.length);
}
private byte[] getByteFromClass(final String name) {
String path = StringUtils.replace(name, ".", File.separator) + ".class";
File f = new File(baseClassName + path);
if (!f.exists() || f.isDirectory()) {
throw new RuntimeException(name + "is not exists!");
}
FileInputStream fileInput = null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] b = new byte[CAPACITY], classByte = null;
try {
int readLen;
fileInput = new FileInputStream(f);
while ((readLen = fileInput.read(b)) != -1) {
byteArrayOutputStream.write(b, 0, readLen);
}
classByte = byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInput != null) {
fileInput.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
fileInput = null;
}
try {
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
byteArrayOutputStream = null;
}
}
return classByte;
}
public static void main(String[] args) throws ClassNotFoundException {
TestClassLoader loader = new TestClassLoader("H:/eclipse/workspace/hib/target/classes");
Class employerManager = loader.loadClass("employ.Employer");
System.out.println(employerManager.getName());
Method[] methods = employerManager.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method.getName());
}
}
}
2 利用URLClassLoader来加载jar包,主要代码如下:
URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL",new Class[] { URL.class });
addURL.setAccessible(true);
//add all the jar file path to classpath
for (File jarFile : jarFiles)
{
addURL.invoke(systemClassLoader, new Object[] { jarFile.toURL() });
}
这部分代码主要用在服务器启动时加载一些jar包
3 自定义ClassLoader来加载jar包
public class MyClassLoader extends URLClassLoader {
//加载类
protected Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name);
}
public MyClassLoader(URL[] urls) {
super(urls);
}
public MyClassLoader(URL[] urls, ClassLoader parent,
URLStreamHandlerFactory factory) {
super(urls, parent, factory);
// TODO Auto-generated constructor stub
}
public MyClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
// TODO Auto-generated constructor stub
}
protected void addURL(URL url) {
super.addURL(url);
}
//查找各种配置文件,例如hibernate.cfg.xml或者hibernate项目下各对象的.hbm.xml文件
public URL findResource(final String name) {
URL url = null;
url = super.findResource(name);
URL contextUrl = this.getResource(".");
//获取该类的classpath
String contextPath = contextUrl.getPath();
try {
if (url == null) {
if (name.startsWith(File.separator)) {
String actualName = name.substring(1);
url = new URL("file://" + contextPath + actualName);
} else {
url = new URL("file://" + contextPath + name);
}
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return url;
}
}
将该类可以放在在一java项目中。
现在我们新建一hibernate项目,在该hibernate项目中,有一个EmployerManager类,该类功能实现是对员工进行管理,该类有一个getEmployer方法,其中类EmployerManager的getEmployer方法代码如下:
public List<Employer> getEmployer() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(Employer.class);
//criteria.add(Restrictions.le("id", 200L));
criteria.setFirstResult(10);
criteria.setMaxResults(50);
List<Employer> employerList = (List<Employer>)criteria.list();
for (Employer employer : employerList) {
System.out.println(employer);
}
session.getTransaction().commit();
return employerList;
}
我们可以利用上述的MyClassLoader来加载hibernate工程下的classes目录下的jar包、classes文件以及xml配置文件
测试类如下(该测试类也在java项目中):
public class Test {
public static void main(String[] args) throws ClassNotFoundException, IOException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, SecurityException, NoSuchMethodException {
File f = new File("H:/eclipse/workspace/hib/target/classes/lib");
String[] paths = f.list();
//hib为hibernate工程名,该工程编译后的所有类文件都在H:/eclipse/workspace/hib/target/classes/目录下,同时将该项目用到的jar包放入H:/eclipse/workspace/hib/target/classes/lib目录下
URL[] urls = {new URL("file:///H:/eclipse/workspace/hib/target/classes/")};
MyClassLoader loader = new MyClassLoader(urls);
for (String s : paths) {
loader.addURL(new URL("file:///H:/eclipse/workspace/hib/target/classes/lib/" + s));
}
Class employerManager = loader.loadClass("employ.EmployerManager");
Method[] methods = employerManager.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("getEmployer")) {
method.invoke(employerManager.newInstance(), null);
}
}
}
}
我们可以看到在Test类中执行该方法时会正确执行getEmployer的方法
4
总结:
1 可以得到jar包的加载方法,这里对于采用获取jar包中每一个类文件的字节进行加载的方法不予介绍(javaeye上可以搜到)。
2 对ClassLoader、URLClassLoader有了一定的了解。对如何加载类、加载jar包、加载资源文件有所了解。对于加载类,我们可以实现findClass方法,对于加载xml,我们可以实现findResource方法
3 疑问:如果该java项目中的lib包中已经有另一hibernate中的某些包(例如hibernate-3.2.6.ga.jar),且这些包的版本相同或者不相同时结果会如何?冲突?
4 对于类加载的安全性检查还没有实现。
分享到:
相关推荐
检查实现类.class文件的修改时间,如果是更新的.class文件则重新加载该实现类的class。 4. 调用方法前,先获取最新的代理类,然后调用代理类的方法。 这样,每次调用代理类中的方法,都会先检查实现类的class文件...
自定义classloader的使用
java自定义类加载classloader文档,包括代码,以及详细的原理及过程
3-7Tomcat中自定义类加载器的使用与源码实现(1).mp4
NULL 博文链接:https://ldbjakyo.iteye.com/blog/1046984
【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!
简单的自定义类加载器问候世界hello word,基于磁盘的ClassLoader
ClassLoader的API使用和自定义
ClassLoader类加载机制和原理详解
Android内存加载运行DEX文件示例代码。 解决自定义CLassLoader加载文件不安全的问题
热修复和插件化是目前比较热门的技术,要想更好的掌握它们需要了解ClassLoader,下面这篇文章主要给大家介绍了关于Android中自定义ClassLoader耗时问题追查的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧
自定义 ClassLoader 加载任何类时的类名。 ":myCommand" 命令位于默认 REPL 命令之上。 scala > val hello = " hello " MyClassLoader loads classOf < root>.$line3 <<中略>> MyClassLoader loads classOf ...
java,自定义加载类的实现。1.自定义加载类的实现。2双亲委派的验证。3如何制定父类加载器。
该电子书详细介绍了java虚拟机类加载机制,对于深入理解jvm工作原理有很好的帮助作用,对于初学java,有一定工作经验的小伙伴来说是一本提高自身java素养,夯实自己java基本技能的“葵花宝典”。
这篇文章主要讲类加载器在android中如何动态的加载其他工程类的过程,对于类加载器的知识就跳过了。
ClassLoader运行机制 自己写的ClassLoader运行机制 自己写的ClassLoader运行机制 自己写的ClassLoader运行机制 自己写的ClassLoader运行机制 自己写的
自定义Java类加载器demo,自定义了一个classLoader,重写了loadClass 和findClass,注意 loadClass打破了双亲委派机制,所有的类都要在自定义的class文件中找到,而findClass遵循了双亲委派机制
Java Applet 需要从远程下载 Java 类文件到浏览器中并执行。现在类加载器在 Web 容器和 OSGi 中得到了广泛的使用。一般来说,Java 应用的开发人员不需要直接同类加载器进行交互。Java 虚拟机默认的行为就已经足够...
ClassLoader类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。从而只有class文件被载入到了内存之后,才能被其程序所引用。所以ClassLoader就是用来动态加载class文件到内存当中用的。 ...
NULL 博文链接:https://lz12366.iteye.com/blog/735289