fantasia兄的建议,我也回去研究下,不过我没用过aspectj,所以不好说,可行不可行,主要,我的目的是做到对系统无侵入,然后才是代理实现监控

我看了aspectj的一点资料,理解不是很透彻,不过初步感觉不是很能满足我的目的。

因为,监控组件本身并不知道需要监控的系统存在什么包,什么类,需要监控什么类什么包,都是通过监控组件自己的配置文件配置。什么时候不想在生产系统监控了,就把配置项去掉。

上面的问题,经过几天的努力已经完全解决了,中间遇到不少隐晦的陷阱,下面我总结一下我对JVM加载类机制的一些理解,有些可能不准确,希望大家指正.

首先,JVM通过系统ClassLoader(C++实现)以及各种自定义ClassLoader来加载所有需要执行的类,自定义的ClassLoader通过父子委托关系实现类加载,关于这些我不多说了,很多资料讲的很详细,特别是Bill Venans的文章。

下面讲讲我理解中的几个概念:命名空间,类的加载

1)命名空间
每个ClassLoader在JVM内部都有独立的命名空间,通过ClassLoader的defineClass方法把一个类注册进命名空间,通过findLoadedClass方法查

找该ClassLoader已经注册在JVM内部的类。JVM统一通过调用ClassLoader的loadClass方法加载一个类,一般来说loadClass方法的实现遵循委

托模式来实现,但这不是一定的,你完全可以不遵照这样的委托模式,但是必须仔细考虑清楚可能影响到系统中其他ClassLoader,有一个相当

重要的概念:不同的ClassLoader加载的类,哪怕名称相同,JVM也认为是不同的类,类型转换的时候会抛错。所以实现自己的ClassLoader就应

该特别注意边界关系了,不应该你去加载的类资源你就不要碰,否则,遇到ClassCastException就不要纳闷了。还有一个重要概念:哪个ClassLoader define了这个类,这个类的getClassLoader就是谁,而不是loadClass。

2)类的加载
JVM通过ClassLoader加载一个类,但是这个时候加载的仅仅是一个类定义,当真正需要执行时,会进行链接,解释,执行等操作。在这个过程

中,首先会使用引用类的加载器去加载所有该类里面引用到的其他类,判断引用关系的合法性,这个时候如果异常会抛出各种LinkedError的子

类。对于Class类,他包含了类定义的基本信息数据,但是代码逻辑定义却只保存在JVM内部,对于字节码定义格式可以参看JVM Spec。

就写这么多,理解的比较浅显,不要拍砖,嘿嘿

我的帖是不是表达的不清楚,为什么没有人参与讨论呢?

根据楼主的描述,我觉得JDK 5.0的Instrumentation可能会更有用些,毕竟你做的只是监控工具。如果一个监控工具都要卸载和重新加载需要监控的类,真是有点奇怪。

这也没什么奇怪的呀,目前一些监控工具有的就有提供对方法调用的监控,比如IBM的,它是通过分析JVM日志实现,或者jprofile,就是通过字节码修改实现,但是它需要通过它的类来启动容器的starup,这点无法接受,生产的系统怎么可能这样做呢?

JDK 5.0的Instrumentation其实也一样是通过字节码修改实现,我只不过自己实现而已,当然,麻烦很多。但是是有很大好处的。

首先我对系统完全没有侵入,需要监控的时候配置上类名,不需要的时候就不配。

另外就是目前公司许多系统都还在1.4上跑,特别是那批使用websphere 5 的。

我自己实现还可以做很多事情,光光是分析方法调用,还不能很好发现系统瓶颈,比如说,我自己可以实现线程跟踪,看看一个线程有多少时间执行数据库操作,有多少时间是在容器内部消耗,有多少时间是在远程调用等等,甚至一个方法调用了几次数据库,方法的调用层级关系,参数等等,都可以监控下来,还可以给监控信息做过滤。

这样系统还有什么问题发现不了呢?

关于修改已加载到虚拟机中的类的一段文字,是javassist教程里的,没试过,希望对你能有用
(http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html)

If the JVM is launched with the JPDA (Java Platform Debugger Architecture) enabled, a class is dynamically reloadable. After the JVM loads a class, the old version of the class definition can be unloaded and a new one can be reloaded again. That is, the definition of that class can be dynamically modified during runtime. However, the new class definition must be somewhat compatible to the old one. The JVM does not allow schema changes between the two versions. They have the same set of methods and fields.