Почему java.net.SocksSocketImpl реализует java.net.Socket по умолчанию в Java?

Вопрос короткий. Почему реализация сокета SOCKS-сокетов является выбором по умолчанию для реализации абстрактного класса java.net.Socket? Na & iuml; vely Я бы ожидал java.net.PlainSocketImpl.

Фон немного сложнее.

Я пытаюсь убить GLASSFISH-12213 (или действительно пытаюсь обойти это). Детали самой ошибки не очень важны - есть собственная библиотека, которая не является потокобезопасной, и некоторые ее одновременные использования из созданной GlassFish области LDAP приводят к сбою JVM.

Чтобы обойти это, я начал работать в обратном порядке: могу ли я избежать использования первой библиотеки? Это привело меня по разным причинам, чтобы посмотреть sun.net.spi.DefaultProxySelector, который отвечает за поиск соответствующего прокси (или нет) для данного URI. Там есть место там, где он вызывает собственный вызов метода, и именно там происходит сбой JVM. Если бы я мог избежать этого звонка, я был бы в бизнесе.

В одном случае я мог бы избежать этого вызова, если бы я мог гарантировать, что значение sun.net.spi.NetProperties.getBoolean("java.net.useSystemProxies") ложно. Если бы это было так, то нативный метод, о котором я говорил ранее, не будет называться. false - это значение по умолчанию, и я ничего не изменил в этом отношении.

(На самом деле это так, очевидно, доказано в экземпляре GlassFish, запущенном на этой машине, где я заметил ошибку. Я не уверен, как этот код, возможно, по-прежнему может загружать родную библиотеку; на другой день.)

Итак, пробирая этот путь, я еще больше поддержал: какой протокол передавался как URI scheme в вызове DefaultProxySelector.select(uri)? Возможно, я мог бы каким-то образом повлиять на глупую вещь, чтобы по-прежнему пропустить этот родной звонок.

Как оказалось, протокол был socket (я предположил, что это, вероятно, что-то вроде ldap, но нет). Этот факт и мое опровергающее предположение подсказывали мне, что где-то в LDAP-сфере открывалось прямое сокет вручную (т.е. Не используя что-то вроде HttpUrlConnection или какой-либо другой абстракции). Разумеется, созданный Sun профиль LDAP-JNDI-моста делает именно это; URI, который передается, равен socket://somehost:389.

Итак, из всего этого , несмотря на то, что я не настроил никакой информации прокси-сервера, не настроил ничего или не сделал ничего, кроме использования прямых значений по умолчанию, оказывается, что JDK пытается использовать прокси-сервер SOCKS. См. метод setImpl() в java.net.Socket и строке 364 или около того SocksSocketImpl.java и проследите его для деталей.

(Это, наконец, говорит о том, что я мог бы пропустить всю эту кодировку, просто добавив в этот элемент системное свойство socksNonProxyHosts=*. Jeez, не должно ли это поведение по умолчанию?)

В результате - и снова, полагая, что DefaultProxySelector по какой-то причине имеет поле hasSystemProxies, установленное на true, несмотря на никакие изменения в конфигурации мной или GlassFish, сорт сорта сада, созданный садовым разнообразием Соединение Sun LDAP вызывает естественный поиск прокси-сервера SOCKS. Может быть, это только я, но это поражает меня как безумие.

Так кто-нибудь читает это - возможно, вы находитесь в команде JDK или знаете кого-то, кто знает или знаете историю здесь, - знаете, почему реализация по умолчанию java.net.Socket всегда ищет прокси-сервер SOCKS?

Обновление: Я вижу, что ответ будет таким: чтобы, если у вас есть системный прокси-сервер, и он включен с помощью SOCKS, через него проходит весь материал. Но если значение по умолчанию java.net.useSystemProxies равно false, как это, то какая точка поиска (по умолчанию) для SOCKS-прокси?

Ответ 1

Реализация сокета по умолчанию SocksSocketImpl, потому что JRE может иметь внешнюю конфигурацию для использования SOCKS через свойства системы -D socksProxyHost и -D socksProxyPort или ProxySelector.setDefault() или через по умолчанию ProxySelector, установленный JRE.

PlainSocketImpl выполняет не эти свойства или классы (потому что это простой сокет и ничего не знает о прокси), и поэтому эти внешние конфигурации будут игнорироваться не были SocksSocketImpl, которые всегда вызывались, чтобы проверить их. Я согласен, что кажется странным, что вы получаете SocksSocketImpl, когда никто ничего не сказал о SOCKS для JRE, но я предполагаю, что архитектура java.net.Socket и ProxySelector не позволяет предварительно выбрать правильный impl во время Socket конкретизации.

Я думаю, что вы (или кто бы ни вел текущую линию расследования этой ошибки в Glassfish), возможно, ошибаются: вместо того, чтобы пытаться подорвать способ, которым JRE выбирает сокеты и прокси-серверы, почему бы не исправить по умолчанию ProxySelector и/или ОС, так что, когда Java выполняет свои стандартные запросы для получения информации о прокси, все не прерывается. Я думаю, что исправление находится в кишках процесса поиска прокси и классов, а не выше.


Возможно, еще один способ спросить, что я спрашиваю: if DefaultProxySelector может сказать мне, что прокси-серверы используют для подключения сокета, почему Socket не вызывает это первым, чтобы помочь ему выбрать разумную реализацию?

Я думаю, проблема в том, что java.net.Socket поддерживает несколько моделей программирования. Там есть очевидный конструктор new Socket(host, port), но есть и конструктор по умолчанию new Socket(), который может быть построен первым, а затем в какое-то произвольное время в будущем может быть вызван его метод connect(SocketAddress).

Поскольку часть критериев, которые a ProxySelector может использовать для определения использования прокси-сервера или нет, - это имя удаленного хоста и удаленного порта, к которому необходимо подключиться (то есть информация, предоставленная connect), конструктор java.net.Socket слишком рано знать, нужен ли прокси-сервер или нет.

По какой-либо причине (можем ли мы просто предположить исторические?/обратные соображения совместимости?:), конструктор для java.net.Socket - единственное место, где установлено impl, и, как я уже сказал, это в некоторых случаях слишком рано говорить нужен ли прокси-сервер или нет.