类加载器特技:OSGi代码生成
2010-03-01 00:00:00 来源:WEB开发网为了防止保留类加载器带来的内存泄露,我们必须使用弱键和弱值。目标是不在内存中保持一个已卸载的bundle的类空间。我们必须使用弱值,因为每个映射项目的值(BridgeClassLoader)都强引用着键(ClassLoader),于是以此方式否定它的“弱点”。这是WeakHashMap javadoc规定的标准建议。通过使用一个弱缓存我们避免了跟踪所有的bundle,而且不必对他们的生命周期做出反应。
可见性
好的,我们终于有了自己的外来的桥接类空间。现在我们如何在其中定义我们的增强类?如前所述问题,defineClass()是 BridgeClassLoader的一个受保护的方法。我们可以用一个公有方法来覆盖它,但这是粗野的做法。如果做覆盖,我们还需要自己编码来检查所请求的增强类是否已经被定义。更好的办法是遵循类加载器设计的意图。该设计告诉我们应该覆盖findClass(),当findClass()认为它可以由任意二进制源提供所请求类时会调用defineClass()方法。在findClass()中我们只依赖所请求的类的名称来做决定。所以我们的 BridgeClassLoade必须自己拿主意:
这是一个对“A$Enhanced”类的请求,所以我必须调用一个叫做"A"的类的增强类生成器!然后我在生成的字节数组上调用defineClass()方法。然后我返回一个新的类对象。
这段话中有两个值得注意的地方。
我们为增强类的名称引入了一个文本协议
- 我们可以给我们的类加载器传入数据的单独一项 - 所请求的类的名称的字符串。同时我们需要传入数据中的两项 - 原始类的名称和一个标志,将其(原始类)标志为增强类的主语。我们将这两项打包为一个字符串,形式为[目标类的名称]"$Enhanced"。现在 findClass()可以寻找增强类的标志$Enhanced,如果存在,则提取出目标类的名称。这样我们引入了我们增强类的命名约定。无论何时,当我们在堆栈中看到一个类名以$Enhanced结尾,我们知道这是一个动态生成的类。为了减少与正常类名称冲突的风险,我们将增强类标志做得尽可能特殊(例如:$__service_proxy__)
更多精彩
赞助商链接