JEP 418: Internet-Address Resolution SPI
SPI для разрешения интернет-адресов
| Ответственный | Aleksej Efimov |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 18 |
| Компонент | core-libs / java.net |
| Обсуждение | net dash dev at openjdk dot java dot net |
| Длительность | S |
| Рецензенты | Alan Bateman, Brian Goetz, Chris Hegarty, Daniel Fuchs |
| Одобрен | Brian Goetz |
| Создан | 2021/03/16 16:43 |
| Обновлён | 2022/09/09 10:29 |
| Задача | 8263693 |
Аннотация
Определить интерфейс поставщика услуг (service-provider interface, SPI) для разрешения имён хостов и адресов, чтобы java.net.InetAddress мог использовать не только встроенный резолвер платформы, но и другие резолверы.
Что не является целью
-
Разработка альтернативного резолвера для включения в JDK не является целью. По умолчанию по-прежнему будет использоваться встроенный резолвер JDK.
-
Поддержка в SPI операций разрешения сверх тех, которые нужны API
InetAddress, не является целью. -
Определение неблокирующих или асинхронных API разрешения не является целью.
Мотивация
API java.net.InetAddress преобразует имена хостов в адреса Internet Protocol (IP) и обратно. Сейчас API использует собственный резолвер операционной системы, который обычно настроен на совместное использование локального файла hosts и системы доменных имён (Domain Name System, DNS).
Причины определить интерфейс поставщика услуг для разрешения имён и адресов:
-
Проект Loom. Сейчас операция разрешения через API
InetAddressблокируется в вызове операционной системы. Для Virtual Threads (виртуальные потоки) проекта Loom, работающих в пользовательском режиме, это проблема: пока операция разрешения не завершится, нижележащие платформенные потоки не могут обслуживать другие потоки Virtual Threads. Альтернативный резолвер мог бы реализовать клиентский протокол DNS напрямую, без блокировки. -
Новые сетевые протоколы. SPI для резолверов позволил бы беспрепятственно интегрировать новые протоколы разрешения, например DNS поверх QUIC, TLS или HTTPS.
-
Настройка. SPI для резолверов дал бы фреймворкам и приложениям более тонкий контроль над результатами разрешения и позволил бы встраивать в существующие библиотеки собственный резолвер.
-
Тестирование. При прототипировании и тестировании часто нужно управлять результатами разрешения имён хостов и адресов, например при создании mock-объектов для компонентов, которые используют API
InetAddress.
Описание
API InetAddress определяет несколько методов для операций поиска:
-
InetAddress::getAllByNameвыполняет прямой поиск: сопоставляет имени хоста набор IP-адресов. -
InetAddress::getByNameтоже выполняет прямой поиск: сопоставляет имени хоста первый адрес из его набора адресов. -
InetAddress::getCanonicalHostNameвыполняет обратный поиск: сопоставляет IP-адресу полное доменное имя. Например:var addressBytes = new byte[] { (byte) 192, 0, 43, 7}; var resolvedHostName = InetAddress.getByAddress(addressBytes) .getCanonicalHostName(); -
InetAddress::getHostNameпри необходимости тоже выполняет обратный поиск.
По умолчанию InetAddress выполняет поиск с помощью собственного резолвера операционной системы. Результат поиска, положительный или отрицательный, может кэшироваться, чтобы не выполнять повторный поиск того же хоста.
Интерфейс поставщика услуг
API InetAddress будет находить поставщика резолвера с помощью загрузчика сервисов. Если поставщик не найден, как и раньше будет использоваться встроенная реализация.
Новые классы в пакете java.net.spi:
-
InetAddressResolverProvider— абстрактный класс, определяющий сервис, который находитjava.util.ServiceLoader. По сути,InetAddressResolverProvider— это фабрика резолверов. Созданный резолвер будет установлен как общесистемный, иInetAddressбудет передавать ему все запросы на поиск. -
InetAddressResolver— интерфейс, определяющий методы для базовых операций прямого и обратного поиска. Экземпляр этого интерфейса получают из экземпляраInetAddressResolverProvider. -
InetAddressResolver.LookupPolicy— класс, экземпляры которого описывают характеристики запроса на разрешение, в том числе запрошенный тип адреса и порядок, в котором должны возвращаться адреса. -
InetAddressResolverProvider.Configuration— интерфейс, описывающий встроенную конфигурацию платформы для операций разрешения. Он даёт доступ к имени локального хоста и встроенному резолверу. Собственные поставщики резолверов используют его, чтобы начальным образом построить резолвер или частично передавать запросы на разрешение собственному резолверу операционной системы.
Альтернативы
Без SPI, подобного предложенному здесь, приложениям придётся и дальше использовать существующие обходные решения.
-
Приложение может искать сетевые имена и адреса с помощью Java Naming and Directory Interface (JNDI) и его поставщика DNS. Этот подход может быть полезен приложениям, которым нужен тонкий контроль над поиском в DNS, но он не связан с
InetAddress, поэтому его использование вместе с сетевым API платформы требует дополнительных усилий. -
Приложение может напрямую использовать библиотеки резолвера операционной системы через Java Native Interface (JNI) или foreign function API из проекта Panama. Однако, как и в случае JNDI, этот подход не связан с
InetAddress, поэтому пользоваться им неудобнее. -
Приложение может с помощью нестандартного системного свойства JDK
jdk.net.hosts.fileнастроитьInetAddressтак, чтобы имена хостов сопоставлялись IP-адресам по заданному файлу, а не через собственный резолвер операционной системы. Эта возможность полезна для тестирования, но не является универсальным решением, поскольку полный список имён хостов не всегда известен заранее.
Тестирование
Мы разработаем новые тесты для SPI резолверов.
Мы разработаем экспериментальные поставщики резолверов (proof of concept), чтобы продемонстрировать и проверить, что с помощью SPI можно разрабатывать и развёртывать альтернативные реализации, которые используются вместо встроенной реализации JDK. Как минимум один из этих поставщиков мы сделаем доступным, чтобы на его основе можно было разрабатывать более полные реализации.