Java библиотека
MAX ·
Как кешировать данные о классах и не удерживать ClassLoader?
Фреймворки часто читают аннотации и методы через reflection. Сохранять такие данные в обычной статической map не всегда безопасно, если приложение выгружает плагины или модули.
Например, типичный кеш хранит ссылку на класс в ключе:
Map, Metadata> cache = new ConcurrentHashMap<>();
Заполнять такой кеш можно через computeIfAbsent:
cache.computeIfAbsent(type, MetadataCache::inspect);
Но долгоживущий кеш удерживает ключи-Class, а вместе с ними может задержать выгрузку ClassLoader. Для данных, привязанных к Class, в Java есть ClassValue.
Опиши вычисление один раз в computeValue:
ClassValue cache = new ClassValue<>() {
protected Metadata computeValue(Class type) {
return inspect(type);
}
};
Значение вычисляется по запросу, отдельно для каждого класса. Оставляй inspect без побочных эффектов, поскольку конкурентные вызовы могут привести к повторному вычислению.
Читай метаданные через get:
Metadata metadata = cache.get(Order.class);
metadata.invoke(order);
Такой доступ не требует вручную синхронизировать создание значения. ClassValue подходит для reflection-кеша, который индексируется объектами Class.
Если значение нужно пересчитать, удали его:
cache.remove(Order.class);
Metadata refreshed = cache.get(Order.class);
Следующий get снова вызовет computeValue. Для обычных кешей с произвольными ключами ClassValue не подходит.
Java Библиотека | Мы в Телеграм
