- 浏览: 623255 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
xianzi_2008:
xianzi_2008 写道楼主请教下,我缓存了一个List& ...
Ehcache -
xianzi_2008:
楼主请教下,我缓存了一个List<Bean>对象, ...
Ehcache -
jsdsh:
收藏好.五个字
hibernate之one-to-many详细 -
Tlife:
好!!!!
hibernate------HQL总结 -
yanqingluo:
例子很恰当。
观察者模式
1.自定义的类加载器
2.Pig类的代码如下:
Pig.class文件拷贝到c:/temp目录下。
出现的问题:在自定义的MyClassLoader中return defineClass("classloader.Pig", b, 0, b.length);报异常:
如果Pig.java不带包名(即去掉:package classloader;)。然后MyClassLoader里相应的包名也都去掉。就完全没问题。
由于你每次加载类都是加载Pig类,所以加载父类就认为循环继承了,所以抛出ClassCircularityError。
关键是为什么会加载2次?也就是说第一次调用完defineClass("Pig")以后,虚拟机会再次使用Pig的loader去加载Pig父类,我找了下Vm spec,有这么一段说明:
这应该很说明问题了,至于下午你说不含包名的那个为什么不报错,是由于你加载文件并不是固定加载Pig,所以不会让虚拟机以为循环继承.
package classloader; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.WritableByteChannel; /** * 加载类----->定义类------>解析类 * loadClass---->defineClass ------>resolveClass */ class MyClassLoader extends ClassLoader { public static void main(String[] args)throws Exception{ ClassLoader loader = new MyClassLoader(); Class clazz = loader.loadClass("classloader.Pig"); Object pig = clazz.newInstance(); System.out.println(pig.toString()); System.out.println(clazz.getClassLoader()); System.out.println(pig); } public MyClassLoader(){ } /* 类加载器 * resolve:参数告诉方法是否需要解析类。在准备执行类之前,应考虑类解析。并不总是需要解析。如果 JVM 只需要知道该类是否存在或找出该类的超类,那么就不需要解析。 */ public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException{ // 目标Class Class clas = null; // 看是否已经加载该类 clas = findLoadedClass( name ); if(clas == null){ clas = findClass(name); } //如果class对象不存在则在系统中查找 if (clas==null) { //它在本地文件系统中寻找类文件,如果存在,就使用 defineClass 将原始字节转换成 Class 对象 //核心:使用的ClassLoader是系统默认的:sun.misc.Launcher$AppClassLoader@131f71a clas = findSystemClass( name ); } if(clas == null){ throw new ClassNotFoundException("该类不存在"); } //是否需要解析该类 if (resolve && clas != null) resolveClass( clas ); return clas; } //构造该类的Class对象 public Class findClass(String name){ try{ byte[] b = loadClassBytes(); if(b == null){ return null; } return defineClass("classloader.Pig", b, 0, b.length); }catch(Exception e){ System.out.print(e.getMessage()); } return null; } /** * 加载编译后字节码文件的数据 */ private byte[] loadClassBytes() throws ClassNotFoundException { try { String classFile = "c:/temp/Pig.class"; FileInputStream fis = new FileInputStream(classFile); FileChannel fileC = fis.getChannel(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); WritableByteChannel outC = Channels.newChannel(baos); ByteBuffer buffer = ByteBuffer.allocateDirect(1024); while (true) { int i = fileC.read(buffer); if (i == 0 || i == -1) { break; } buffer.flip(); outC.write(buffer); buffer.clear(); } fis.close(); return baos.toByteArray(); } catch (IOException fnfe) { throw new ClassNotFoundException(className); } } }
2.Pig类的代码如下:
package classloader; public class Pig { public static void main(String[] args){ System.out.println("OK"); } }
Pig.class文件拷贝到c:/temp目录下。
出现的问题:在自定义的MyClassLoader中return defineClass("classloader.Pig", b, 0, b.length);报异常:
Exception in thread "main" java.lang.ClassCircularityError: classloader/Pig at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at classloader.MyClassLoader.findClass(MyClassLoader.java:69) at classloader.MyClassLoader.loadClass(MyClassLoader.java:40) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClassInternal(Unknown Source) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(Unknown Source) at java.lang.ClassLoader.defineClass(Unknown Source) at classloader.MyClassLoader.findClass(MyClassLoader.java:69) at classloader.MyClassLoader.loadClass(MyClassLoader.java:40) at java.lang.ClassLoader.loadClass(Unknown Source) at classloader.MyClassLoader.main(MyClassLoader.java:19)
如果Pig.java不带包名(即去掉:package classloader;)。然后MyClassLoader里相应的包名也都去掉。就完全没问题。
评论
6 楼
llp20_2000
2008-10-17
<p> 最近搜索class文件加密的方法,去重写ClassLoader类.也遇到实例化两次的情况.</p>
<p> 借宝地一用<img src='/images/smiles/icon_smile.gif' alt=''/></p>
<p> 我自定义的类加载器,在</p>
<p> <span style='white-space: pre;'>protected final <a title='java.lang 中的类'>Class</a><?> <strong>defineClass</strong>(<a title='java.lang 中的类'>String</a> name,</span></p>
<p><span style='font-family: simsun; font-size: 16px;'>
</span></p><pre> byte[] b,
int off,
int len)
throws <a title='java.lang 中的类'>ClassFormatError</a></pre>
<pre>定义类的时候,(<span style='white-space: normal;'>目标类是 %classpath%/applicationmain.MainGui.class ). </span></pre>
<p/>
<p> 总是抛出异常</p>
<p> <span style='white-space: pre;'>Exception in thread "main" java.lang.NoClassDefFoundError: MainGui (wrong name: applicationmain/MainGui)</span></p>
<pre name='code' class='java'> at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at myclassloader.MyClassLoader.findClass(MyClassLoader.java:186)
at myclassloader.MyClassLoader.loadClass(MyClassLoader.java:145)
at myclassloader.MyClassLoader.loadClass(MyClassLoader.java:85)
at myclassloader.MyClassLoader.main(MyClassLoader.java:435)
</pre>
<p> </p>
<p> 但是如果我在classpath下直接定义一个Test类.即路径是 %classpath%/Test.class 类加载就是成功的.定义类跟包有关系吗?</p>
<p> </p>
<p> </p>
<p> 另外, <span style='font-family: simsun; font-size: 16px;'><code><strong><a>defineClass</a></strong>(<a title='java.lang 中的类'>String</a> name, byte[] b, int off, int len)</code> 方法中的第一参数name是要加载类的全名,即 "包名.类名" 吗?而不是类名吗? 如<span style='font-family: -webkit-monospace;'><strong><a>defineClass</a></strong>("<span style='color: #0000ee; text-decoration: underline;'>application.Test"</span>,.....</span></span></p>
<p> 或者<span style='font-family: -webkit-monospace; font-size: 16px;'><strong><a>defineClass</a></strong>("<span style='text-decoration: underline; color: #0000ee;'>Test"</span>,.....</span></p>
<p style='margin: 0px;'> </p>
<p> </p>
<p> </p>
<p> </p>
<div><br/></div>
<p> </p>
<p> </p>
<p> </p>
<p> 借宝地一用<img src='/images/smiles/icon_smile.gif' alt=''/></p>
<p> 我自定义的类加载器,在</p>
<p> <span style='white-space: pre;'>protected final <a title='java.lang 中的类'>Class</a><?> <strong>defineClass</strong>(<a title='java.lang 中的类'>String</a> name,</span></p>
<p><span style='font-family: simsun; font-size: 16px;'>
</span></p><pre> byte[] b,
int off,
int len)
throws <a title='java.lang 中的类'>ClassFormatError</a></pre>
<pre>定义类的时候,(<span style='white-space: normal;'>目标类是 %classpath%/applicationmain.MainGui.class ). </span></pre>
<p/>
<p> 总是抛出异常</p>
<p> <span style='white-space: pre;'>Exception in thread "main" java.lang.NoClassDefFoundError: MainGui (wrong name: applicationmain/MainGui)</span></p>
<pre name='code' class='java'> at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
at java.lang.ClassLoader.defineClass(ClassLoader.java:465)
at myclassloader.MyClassLoader.findClass(MyClassLoader.java:186)
at myclassloader.MyClassLoader.loadClass(MyClassLoader.java:145)
at myclassloader.MyClassLoader.loadClass(MyClassLoader.java:85)
at myclassloader.MyClassLoader.main(MyClassLoader.java:435)
</pre>
<p> </p>
<p> 但是如果我在classpath下直接定义一个Test类.即路径是 %classpath%/Test.class 类加载就是成功的.定义类跟包有关系吗?</p>
<p> </p>
<p> </p>
<p> 另外, <span style='font-family: simsun; font-size: 16px;'><code><strong><a>defineClass</a></strong>(<a title='java.lang 中的类'>String</a> name, byte[] b, int off, int len)</code> 方法中的第一参数name是要加载类的全名,即 "包名.类名" 吗?而不是类名吗? 如<span style='font-family: -webkit-monospace;'><strong><a>defineClass</a></strong>("<span style='color: #0000ee; text-decoration: underline;'>application.Test"</span>,.....</span></span></p>
<p> 或者<span style='font-family: -webkit-monospace; font-size: 16px;'><strong><a>defineClass</a></strong>("<span style='text-decoration: underline; color: #0000ee;'>Test"</span>,.....</span></p>
<p style='margin: 0px;'> </p>
<p> </p>
<p> </p>
<p> </p>
<div><br/></div>
<p> </p>
<p> </p>
<p> </p>
5 楼
ttitfly
2008-09-23
把public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException函数注释掉就可以了
4 楼
zyhwxq
2008-09-23
hi ttitfly
你好 能不能把你能运行的代码再上传一下.
你好 能不能把你能运行的代码再上传一下.
3 楼
ttitfly
2008-09-17
多谢大兵瑞恩(leadyu)指点
为什么调用完defineClass("Pig")以后,虚拟机会再次使用Pig的loader去加载Pig父类?
有个C类,被D类引用,那么当加载D类时就有3种情况,其中一种就是说,加载完D以后再加载所有D引用到的类,所以虚拟机又发起一个loadClassInternal.也就是说用加载D的classLoader去加载 包括去加载父类。
但一般来说父类已经被加载了,只不过上面写的loader并没有遵循委托策略,所以又重复define一次
也就是自定义的loader总有一个父loader,loadClass时总是先问父是否已加载,最后才是自己加载,也就是说,自己只负责自己关心得那些目录下的类文件,其他的都一级级委托给其他loader。一般来说是采用父子委托,但中间件有时也采用向下委托,反正要保证loader之间不会有交叉的边界,否则就乱了,所以自己实现loader,一般不改写loadClass方法,只复写findClass,因为这种策略其实已经内置了。
为什么调用完defineClass("Pig")以后,虚拟机会再次使用Pig的loader去加载Pig父类?
有个C类,被D类引用,那么当加载D类时就有3种情况,其中一种就是说,加载完D以后再加载所有D引用到的类,所以虚拟机又发起一个loadClassInternal.也就是说用加载D的classLoader去加载 包括去加载父类。
但一般来说父类已经被加载了,只不过上面写的loader并没有遵循委托策略,所以又重复define一次
也就是自定义的loader总有一个父loader,loadClass时总是先问父是否已加载,最后才是自己加载,也就是说,自己只负责自己关心得那些目录下的类文件,其他的都一级级委托给其他loader。一般来说是采用父子委托,但中间件有时也采用向下委托,反正要保证loader之间不会有交叉的边界,否则就乱了,所以自己实现loader,一般不改写loadClass方法,只复写findClass,因为这种策略其实已经内置了。
2 楼
leadyu
2008-09-16
引用
已解决,是因为还需要loadClassPig的父类Object一次。
由于你每次加载类都是加载Pig类,所以加载父类就认为循环继承了,所以抛出ClassCircularityError。
关键是为什么会加载2次?也就是说第一次调用完defineClass("Pig")以后,虚拟机会再次使用Pig的loader去加载Pig父类,我找了下Vm spec,有这么一段说明:
引用
5.3 Creation and Loading
Creation of a class or interface C denoted by the name N consists of the construction in the method area of the Java virtual machine (§3.5.4) of an implementation-specific internal representation of C. Class or interface creation is triggered by another class or interface D, which references C through its runtime constant pool. Class or interface creation may also be triggered by D invoking methods in certain Java class libraries (§3.12) such as reflection.
Creation of a class or interface C denoted by the name N consists of the construction in the method area of the Java virtual machine (§3.5.4) of an implementation-specific internal representation of C. Class or interface creation is triggered by another class or interface D, which references C through its runtime constant pool. Class or interface creation may also be triggered by D invoking methods in certain Java class libraries (§3.12) such as reflection.
引用
The Java virtual machine uses one of three procedures to create class or interface C denoted by N:
If N denotes a nonarray class or an interface, one of the two following methods is used to load and thereby create C :
If D was defined by the bootstrap class loader, then the bootstrap class loader initiates loading of C (§5.3.1).
If D was defined by a user-defined class loader, then that same user-defined class loader initiates loading of C (§5.3.2).
If N denotes a nonarray class or an interface, one of the two following methods is used to load and thereby create C :
If D was defined by the bootstrap class loader, then the bootstrap class loader initiates loading of C (§5.3.1).
If D was defined by a user-defined class loader, then that same user-defined class loader initiates loading of C (§5.3.2).
这应该很说明问题了,至于下午你说不含包名的那个为什么不报错,是由于你加载文件并不是固定加载Pig,所以不会让虚拟机以为循环继承.
1 楼
ttitfly
2008-09-16
已解决,是因为还需要loadClassPig的父类Object一次。
发表评论
-
常用小代码段和开发经验收集
2011-04-21 14:47 985工作中用到的笔记,方便查找,不断补充。 1,截取过长的文字部分 ... -
java.lang.UnsupportedClassVersionError: Bad version number in .class file
2009-08-26 12:25 3899转载:http://www.blogjava.net/hwpo ... -
java调用dll(Eclipse+CDT+MinGW)
2009-03-06 15:25 6549第一步:配置环境 需要安装CDT和MinGW. CDT:因为 ... -
servlet2.5与el表达式
2008-11-23 15:23 2672Servlet2.4版本默认支持EL,如果在MyEclipse ... -
自定义标签调用资源文件
2008-05-12 22:28 1968自定义标签处理类一般都继承TagSupport或BodyTag ... -
Failed to install Tomcat6 service(Tomcat6安装失败解决方法)
2008-05-06 16:24 11719转载 :http://www.handandaily.com/ ... -
tomcat5.5日志配置
2008-05-06 16:13 2525tomcat5.5日志配置: 从Tomcat5.5后,默认设置 ... -
java List<String>集合 传递值给js的数组
2008-04-21 18:12 5340<script> var intIndex= ... -
c3p0 com.mysql.jdbc.CommunicationsException异常
2008-02-18 17:32 6242使用c3p0,偶尔会报异常: 2008-02-18 10:52 ... -
Pattern Matcher
2008-02-18 10:30 1946package test; import java. ... -
FileUpload组件上传文件
2008-01-23 03:05 6707利用FileUpload组件上传文件,需要到apache上下载 ... -
hibernate大字段处理
2008-01-21 16:45 3212hibernate大字段处理:以mysql为例 比如传张图片, ... -
一个页面嵌套一个页面
2008-01-15 10:45 3546一个页面嵌套一个页面,比如a.jsp嵌套b.jsp那么可以用 ... -
java clone
2008-01-13 18:17 59531.java里的clone分为: A:浅复制(浅克隆): 浅复 ... -
修改Eclipse注释里的${Date}变量格式
2008-01-08 15:47 82241.eclipse3.3里${date}日期格 ... -
List移除元素
2008-01-05 16:16 24831. Iterator的remove()是移除从集合里取出来的 ... -
JDom处理xml
2008-01-05 13:51 21161.DOM的缺点主要是由于DOM是一个接口定义语言(IDL), ... -
观察者模式
2008-01-03 00:45 21385观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听 ... -
DelegatingRequestProcessor
2007-12-27 11:30 3695采用DelegatingRequestProcessor将处理 ... -
Dom and Sax
2007-12-26 20:20 1205jaxp: java apis for xml parsing ...
相关推荐
标题和描述中提到的解决方案是通过自定义`ClassLoader`来处理`serialVersionUID`不一致的问题。以下是几种常见方法的优缺点以及自定义`ClassLoader`的详细解释: 1. **修改序列化byte数据**: 这种方法直接修改已...
- 示例可能还涉及到了对异常处理的演示,因为自定义加载过程中可能会遇到找不到类或非法类文件的问题。 了解和掌握ClassLoader的概念及其应用,对于理解和调试复杂的Java应用程序,尤其是涉及到动态加载和插件化...
同时,当遇到“双亲委派模型”(Parent Delegation Model)引发的问题,如类加载异常时,了解ClassLoader的运作方式可以更快定位和解决问题。 总的来说,Java ClassLoader机制是Java平台的核心特性之一,它使得程序...
这些代码可能展示了如何创建自定义ClassLoader,以及如何使用ClassLoader加载非标准位置的类。通过分析这些示例,我们可以更好地理解ClassLoader的工作机制。 总的来说,理解和掌握JVM ClassLoader对于优化Java应用...
1. **自定义ClassLoader**:Java允许我们创建自定义的ClassLoader,这通常用于实现动态加载类的需求。自定义ClassLoader需要重写`findClass()`或`loadClass()`方法。`loadClass()`方法是类加载的入口,它会调用`find...
如果ClassLoader在加载过程中遇到问题,如找不到类或类定义错误,会抛出ClassNotFoundException或NoClassDefFoundError等异常,需要开发者进行适当的异常处理。 总之,理解ClassLoader的工作原理和机制,可以帮助...
了解Tomcat的ClassLoader源码,有助于我们在开发过程中遇到类加载问题时进行调试,比如解决类冲突、优化资源加载效率,甚至定制化类加载行为以适应特定的应用场景。 通过阅读和分析`icpc2013.pdf`这个文件,虽然其...
1. **安全性增强**:在执行不可信代码前,可以使用自定义ClassLoader进行数字签名验证,增加系统的安全性。 2. **定制化构建**:根据用户特定需求动态创建类,实现更为灵活的应用逻辑。 3. **来源多样化**:可以从...
《深入Java虚拟机(七)深入源码看...深入学习ClassLoader不仅可以提高编程能力,也有助于解决实际开发中遇到的复杂问题。通过阅读源码,我们可以更深入地了解ClassLoader的工作机制,从而更好地利用Java平台的特性。
同时,持续反思和总结是成长的关键,每周回顾自己的学习进度和遇到的问题,有助于及时调整学习策略,更好地适应实习岗位。 总的来说,作为Java工程师,熟悉JVM的工作原理和ClassLoader机制是基础,而能够灵活运用...
用户还可以自定义类加载器,继承`java.lang.ClassLoader`,实现自己的类加载策略。类加载器可以在预期需要某个类时预加载,但如果预加载失败,只有在类被首次主动使用时才会抛出错误。 连接阶段的验证是保证类正确...
3. **自定义ClassLoader** `ClassLoader`是Java中用于加载类的抽象类。Java默认提供了一些ClassLoader,如`Bootstrap ClassLoader`、`Extension ClassLoader`和`Application ClassLoader`。开发者也可以通过继承`...
Java独立钻石问题,通常指的是在Java编程中遇到的类加载器问题,特别是在处理类的继承关系时出现的类冲突现象。这个问题源于Java的类加载机制,即类加载器(ClassLoader)如何查找和加载类。在Java中,每个类都有一...
这里需要注意,因为新编译的类不在原始的ClassPath中,所以需要自定义ClassLoader,比如使用URLClassLoader。 ```java URL classUrl = new File("path/to/compiled/classes").toURI().toURL(); // 替换为实际的编译...
这篇博文“JAVA类加载器分析--热部署的缺陷”探讨了Java类加载机制以及在热部署场景下可能遇到的问题。热部署允许开发者在不重启应用的情况下更新代码,提高开发效率,但同时也存在一些挑战。 首先,我们来理解类...
总之,理解和掌握Java虚拟机的运行机制对于Java开发人员来说至关重要,它不仅能够帮助我们编写出更高效、更稳定的代码,还能让我们在遇到问题时能迅速找到解决方案,提升整个系统的运行效率。通过阅读《Java虚拟机第...
4. **自定义Classloader**:对于特别复杂的依赖情况,可以考虑使用自定义的类加载器来隔离不同的类路径,从而避免类加载冲突。 #### 示例代码 下面是一个简单的示例,展示了如何在Spring应用中引入Tuscany和Axis的...
在学习过程中,可能会遇到一些混淆的问题,比如类装载器的委托模型、类的加载顺序以及如何自定义类装载器以加载非标准路径的类。理解这些概念有助于解决实际开发中遇到的类加载问题,例如,当需要加载外部库或者...