在字节伙伴中缓存生成的类? [英] Caching generated classes in Byte Buddy?

查看:48
本文介绍了在字节伙伴中缓存生成的类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用CGLIB的Enhancer一段时间了,但考虑切换到Byte Buddy。这是非常基本的东西,最多可按需创建数百个数据访问接口的代理。

I have been using CGLIB's Enhancer for a while, but considering to switch over to Byte Buddy. It's pretty basic stuff, proxy for up to a few hundred data access interfaces, created on demand.

Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(...);
enhancer.setSuperclass(...);
enhancer.setInterfaces(...);
enhancer.setCallback(...);
enhancer.create();

CGLIB正在缓存生成的类型以提高性能。字节好友推荐的方法是什么?我想避免任何PermGen问题。

CGLIB is caching the generated type to improve performance. What is the recommended approach with Byte Buddy? I want to avoid any PermGen issues.

推荐答案

更新:自1.6版以来,字节好友提供了 TypeCache 类,该类使用软引用或弱引用作为用于使用自定义键编写缓存的蓝图。此缓存包含一个回调方法 findOrInsert ,该方法允许按需创建类型。

UPDATE: Since version 1.6, Byte Buddy provides the TypeCache class which uses soft or weak references as a blueprint for writing a cache with a custom key. This cache contains a callback method findOrInsert which allows on demand creation of a type.

带字节好友,您应该编写自己的缓存,因为您最了解以下内容:

With Byte Buddy, you should write your own cache because it is you who knows best about:


  • 什么条件对缓存有意义-也许您需要两个具有不同身份的相似类?字节伙伴不应该为您决定这一点。

  • 维护高速缓存需要保留哪些信息? Cglib需要跟踪所有输入信息,即使对于使用短期类加载器加载的类,也可以防止垃圾收集。

cglib使用带有同步映射的静态字段形式保留内部缓存,这有一些严重的限制。使用此缓存,使用缓存时查询 any Enhancer 实例时,由您决定类的标识的不再是您。此外,静态字段需要跟踪创建类的参数,例如输入回调的标识,这可能很繁琐。 (事实上​​,它本身会造成内存泄漏。)

cglib is keeping an internal cache in form of a static field with a synchronized map what bears some serious limitations. With this cache, it is not longer you who decides on the identity of a class when querying any Enhancer instance when using the cache. Furthermore, the static field needs to keep track on the arguments for creating a class as for example the identity of the input callbacks which can be quite heavy. (As a matter of fact create memory leaks by itself.)

Byte Buddy希望成为一个用于生成任何Java类的API,而不仅仅是用于创建代理。因此,您应该最清楚哪种缓存才有意义。考虑您只想代理一个实例的情况。编写一个简单的外观,例如:

Byte Buddy wants to be an API for generating any Java class, not only for creating proxies. Therefore, you should know best what kind of caching makes sense. Considering your scenario where you only want to proxy an instance. Write a simple facade like:

class MyProxyGenerator {
  static Map<Class<?>, Class<?>> proxies = new HashMap<>();
  public Class<?> makeProxy(Class<?> type) {
    if(proxies.contains(type)) {
      return proxies.get(type);
    } else {
      Class<?> proxy = doMakeProxy(type);
      proxies.put(type, proxy);
      return proxy;
    }
  }
  private Class<?> doMakeProxy(Class<?> type) {
    // use Byte Buddy here.
  }
}

这里的优点是您只需要保持跟踪输入类作为缓存引用,如果您的应用程序是单线程的,则可以避免同步。另外,如果可以更好地满足您的用例,则可以将缓存定义为非静态的。甚至更好:您可以使用真正的缓存实现。这样,每个图书馆都可以做到最好。 Byte Buddy可以创建类,而缓存可以缓存。

The advantage here is that you only need to keep track of the input class as a cache reference and you can avoid synchronization if your application was single threaded. Also, you could define your cache to be non-static if that would fit your use case better. And even better: You could use a real cache implementation. This way, every library can do what it can do best. Byte Buddy can create classes and the cache can, well, cache.

为全面披露,我是Byte Buddy的作者,在使用cglib和javassist一段时间。我在使用它们的缓存时遇到了几个问题,这就是为什么我决定不将Byte Buddy附带此类缓存的原因。我相信这更多是由JDK代理的隐式缓存引入的约定,但是由于上述原因,我认为这些缓存通常不是一个好主意。

For full disclosure, I am the author of Byte Buddy and I decided on this approach after using cglib and javassist for a while. I have experienced several problems with their caches which is why I decided to not ship Byte Buddy with such a cache. I believe it is more of a convention which was introduced by the JDK proxy's implicit caching but I do not believe that these caches are generally a good idea for the reasons described above.

这篇关于在字节伙伴中缓存生成的类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆