На сайте OpenJDK появился новый JEP 371, в котором предлагается ввести в язык специальный тип классов, называемых скрытыми. Скрытые классы будут стандартной заменой существующего метода sun.misc.Unsafe.defineAnonymousClass()
, который станет deprecated for removal. Скрытый класс – это класс, который обладает следующими характеристиками:
- Скрытый класс создаётся во время выполнения с помощью нового метода
Lookup.defineHiddenClass()
. - На такой класс не могут прямо ссылаться другие классы. Всё его использование может осуществляться исключительно через рефлексию.
- Такой класс является необнаружимым: его нельзя найти ни по имени, ни обнаружить с помощью загрузчиков классов (через
Class.forName()
,ClassLoader.loadClass()
,ClassLoader.findLoadedClass()
и т.д.) - Имя скрытого класса получается конкатенацией его имени в байт-коде, символа
'/'
и суффикса, который зависит от реализации JVM. Например,com.example.Foo/1234
. - Методы скрытых классов не появляются в стек-трейсах, если не включить опции
-XX:+UnlockDiagnosticVMOptions
и-XX:+ShowHiddenFrames
.
Основной мотиватор введения в язык скрытых классов – предоставить надёжный и гибкий инструмент для фреймворков, динамически генерирующих классы во время выполнения. Скрытые классы смогут генерироваться фреймворком в любом количестве, а детали генерации будут надёжно скрыты от пользователя. За примером далеко ходить не надо: сама Java генерирует множество классов во время выполнения, которые было бы неплохо сделать скрытыми (прокси-классы, тела лямбд, классы после трансляции из JavaScript и т.д.)
Lookup.defineHiddenClass()
также будет поддерживать агрессивную выгрузку посредством слабых скрытых классов, которые можно будет создавать, указав опцию WEAK
. На такие классы не будет сильной ссылки со стороны загрузчика класса, а значит, он не будет мешать его утилизации сборщиком мусора. Это предотвратит неконтролируемый рост скрытых классов в памяти.