|
Spec-Zone .ru
спецификации, руководства, описания, API
|
Naming.lookup?_Stub файл в клиенте CLASSPATH? Я думал, что это могло быть загружено.ClassNotFoundException?java.lang.ClassMismatchError выполняя мою программу?ArrayStoreException. Что продолжается?ClassNotFoundException для моего тупикового class, когда я пытаюсь зарегистрировать удаленный объект в реестре. Что происходит?java.net.UnknownHostException?UnknownHostException?Naming.bind и Naming.lookup необычно потребуйтесь много времени на Windows?java.net.SocketException: Address already in use"когда я пытаюсь выполнить реестр?System.exit для корректного клиентского завершения?unreferenced() метод не становится вызванным до спустя десять минут после того, как я прекратил использовать удаленный объект! Как я могу сократить эту задержку?rmic команда в пакетном файле DOS?select() вызвать. Реестр реализуется, опрашивая?Serializable чтобы быть записанным ObjectOutputStream?ObjectInputStream от ObjectOutputStream без файла промежуточный?writeObject метод и получает это использующий readObject метод. Если я тогда изменяю значение поля в объекте и отправляю это как прежде, объект что readObject возвраты метода, кажется, то же самое как первый объект и не отражают новое значение поля. Я должен испытывать это поведение?Serializable но подкласс B реализации Serializable, будут поля class A быть сериализированными, когда B будет сериализирован?Naming.lookup?Даже если сервер будет ошибочен о своем имени узла или IP-адресе (или имеет имя узла, которое просто не разрешимо клиентами), то это все еще экспортирует все свои объекты, используя, что ошибочное имя узла, но Вы будете видеть исключение каждый раз, когда Вы пытаетесь получить один из тех объектов.
Имя узла, в котором Вы определили Naming.lookup определять местоположение реестра не имеет никакого эффекта на имя узла, которое уже встраивается в удаленную ссылку на сервер.
Обычно, таинственное имя узла является неполным именем узла сервера, или частным именем, неизвестным nameservice клиента, или (в случае платформ Windows) Сеть сервера-> Идентификация-> Машинное Имя.
Соответствующее обходное решение должно установить системное свойство java.rmi.server.hostname запуская сервер. Значение свойства должно быть внешне достижимым именем узла (или IP-адрес) сервера - безотносительно работ когда определено как часть узла в Naming.lookup достаточно хорошо.
Для большего количества детали см. вопросы на обратных вызовах и полностью определенных доменных именах.
_Stub файл в клиенте CLASSPATH? Я думал, что это могло быть загружено.java.rmi.server.codebase свойство, которое указывает на расположение от того, где тупиковый class может быть загружен. Следует установить java.rmi.server.codebase свойство на сервере, экспортирующем удаленный объект. В то время как удаленные клиенты могли установить это свойство, они будут тогда ограничены только получением удаленных объектов от указанной кодовой базы. Недопустимо предположить, что любой клиент, VM определит кодовую базу, которая решает к расположению Вашего объекта. Когда удаленный объект упорядочивается по Java RMI (ли как параметр удаленному вызову или как возвращаемое значение), кодовая база для тупикового class получается Java RMI и используется, чтобы аннотировать сериализированный тупик. Когда тупик неупорядочивается, кодовая база используется, чтобы загрузить тупик classfile использование RMIClassLoader, если class не может уже быть найден в CLASSPATH или контекстом classloader для объекта получения, такого как кодовая база апплета.
Если _Stub class был загружен RMIClassLoader, тогда Java RMI уже знает который кодовая база использовать для ее аннотации. Если _Stub class был загружен из CLASSPATH, тогда нет никакой очевидной кодовой базы, и Java, с которым RMI консультируется java.rmi.server.codebase системное свойство, чтобы найти кодовую базу. Если системное свойство не устанавливается, то тупик упорядочивается с нулевой кодовой базой, что означает, что это не может использоваться, если у клиента нет соответствующей копии _Stub classfile в клиенте CLASSPATH.
Легко забыть определять свойство кодовой базы. Один способ обнаружить эту ошибку состоит в том, чтобы запуститься rmiregistry отдельно и без доступа к классам приложений. Это вызовет Naming.rebind перестать работать, если кодовая база опускается.
Для получения дополнительной информации по java.rmi.server.codebase свойство, пожалуйста, смотрите на наше учебное руководство, Динамическая загрузка кода, используя Java RMI (Используя java.rmi.server.codebase Свойство).
java.rmi.server.codebase свойство, чтобы использовать любой допустимый протокол URL, такой как file или ftp. Используя сервер HTTP только делает Вашу жизнь более простой, обеспечивая автоматизированный механизм для загрузки файла class. Если у Вас нет доступа к серверу HTTP, ни наклону установить один, можно использовать наш маленький файловый сервер class, найденный в . ClassNotFoundException?java.rmi.server.codebase свойство не было установлено (или не был установлен правильно) на VM, который экспортирует Ваш удаленный объект (ы). Пожалуйста, смотрите на наше учебное руководство, Динамическая загрузка кода, используя Java RMI (Используя java.rmi.server.codebase Свойство). hashCode и equals методы соответственно. Если клиентская фабрика сокета не реализует эти методы правильно, другое разветвление - то, что тупики (использующий клиент снабжают фабрику сокетом), которые обращаются к тому же самому удаленному объекту, не будут равны. Java реализация RMI пытается снова использовать серверные порты также. Это только сделает так, если будет существующий сокет сервера для порта, создаваемого эквивалентной фабрикой сокета. Удостоверьтесь фабрика сокета сервера, которую class реализует hashCode и equals методы также.
Если у Вашей фабрики сокета нет никакого состояния экземпляра, тривиальной реализации hashCode и equals методы являются следующим:
public int hashCode() { return 57; }
public boolean equals(Object o) { return this.getClass() == o.getClass() }
javaw команда выбрасывает вывод к stdout и stderr, так для того, чтобы отладить цели лучше работать java команда в отдельном окне так, чтобы можно было видеть, сообщила об ошибках. Чтобы сделать это, выполните команду как следующее:
start java EchoImpl
Советуют не использовать javaw команда во время разработки. Чтобы наблюдать действие сервера, запустите сервер с -Djava.rmi.server.logCalls=true.
java.lang.ClassMismatchError выполняя мою программу?java.rmi.registry.RegistryImpl). Это должно разрешить вещи. ArrayStoreException. Что продолжается?
FooRemote[] f = new FooRemote[10];
for (int i = 0; i < f.length; i++) {
f[i] = new FooRemoteImpl();
}
Теперь Java RMI может поместить тупик в каждую ячейку массива без исключения на удаленном вызове.
Распределенные объекты ведут себя по-другому чем локальные объекты. Если Вы просто снова используете локальную реализацию, не обрабатывая блокировку и отказ, то Вы, вероятно, получите непредсказуемые результаты.
ClassNotFoundException для моего тупикового class, когда я пытаюсь зарегистрировать удаленный объект в реестре. Что происходит?Когда Вы делаете звонок в реестр, чтобы связать объект, реестр фактически связывает ссылку на тупик для удаленного объекта. Чтобы инстанцировать тупикового объекта, реестр, VM должен быть в состоянии загрузить свое определение class. VM (в этом случае сервер VM), который отправляет сериализированные формы тупика в удаленном вызове метода реестра, ответственен за аннотирование тупика расположением, с которого могут быть загружены его классы. Если тупики не будут аннотироваться должным образом, Java, то RMI бросит a ClassNotFoundException когда это пытается инстанцировать тупика.
Чтобы аннотировать классы должным образом, сервер должен установить значение java.rmi.server.codebase значение свойства к расположению (ям) тупиковых классов. Java RMI автоматически аннотирует сериализированную форму исходящих объектных экземпляров со значением java.rmi.server.codebase свойство.
ОТМЕТЬТЕ: возможно (и в небольшом количестве соответствующих сред) позволить rmiregistry неупорядочить тупиковые объекты, помещая все соответствующие тупиковые файлы class в ПУТЬ К КЛАССУ rmiregistry. Однако, rmiregistry не должен загрузить тупиковые классы. Если тупиковые классы будут доступны локально, то это будет использовать те классы. Используя ПУТЬ К КЛАССУ rmiregistry для тупикового развертывания требует, чтобы у всех VMs, которые ссылаются на тупиковый экземпляр, полученный из того реестра, был файл class тупика, установленный локально (в ПУТИ К КЛАССУ VM).
Например, если реестр загрузит тупиковые классы из своего ПУТИ К КЛАССУ, когда реестр отправит сериализированные тупиковые объекты другому VMs, то те сериализированные объекты будут аннотироваться значением реестра java.rmi.server.codebase свойство (который почти всегда будет нулем). Если VMs, у получения сериализированных тупиковых объектов от реестра нет файлов class для тех тупиков установленными локально тогда те VMs, вероятно, бросят a ClassNotFoundException.
Вместо этого если классы загружаются динамически с VM's сервера java.rmi.server.codebase аннотация, только сервер у VM должны быть тупиковые классы в его ПУТИ К КЛАССУ. С этим подходом развертывание приложения более просто, и возможно ввести новые тупиковые версии в рабочую распределенную систему.
Для получения дополнительной информации по динамической загрузке кода в Java RMI, пожалуйста, см. учебное руководство, Динамическая загрузка кода, используя Java RMI (Используя java.rmi.server.codebase).
java -Djava.rmi.server.logCalls=true YourServerImpl
где YourServerImpl имя Вашего сервера. Если Ваш сервер завис, можно получить дамп монитора и распараллелить дамп, делая ctrl-\ на Операционной системе Solaris™ (Солярис ОС) и ctrl-break на платформах Windows. java.rmi."элементы общедоступной спецификации и документируются в Java Спецификация RMI. Свойства, которые начинаются"sun.rmi."только поддерживаются определенными версиями Java Комплект разработчика SE (JDK) программное обеспечение от Sun Microsystems. В то время как они"sun.rmi.*"свойства могут быть довольно полезными для отладки и настройки во времени выполнения, пожалуйста, отметьте, что их не считают частью общедоступного API, и их использование подвержено изменениям (или может быть удален полностью) в будущих версиях реализации.
Для Java клиент RMI, чтобы связаться с удаленным Java сервер RMI, клиент должен сначала содержать ссылку на сервер. Naming.lookup вызов метода является наиболее распространенным механизмом, которым клиенты первоначально получают ссылки на удаленные серверы. Удаленные ссылки могут быть получены другими средствами, например: все удаленные вызовы метода могут возвратить удаленные ссылки. Это что Naming.lookup делает; это использует известный тупик, чтобы сделать удаленный вызов метода rmiregistry, который отсылает удаленную ссылку назад на объект, который требуют lookup метод.
Каждая удаленная ссылка содержит имя узла сервера и номер порта, которые позволяют клиентам определять местоположение VM, который служит определенному удаленному объекту. Однажды Java у клиента RMI есть удаленная ссылка, клиент будет использовать имя узла и порт, обеспеченный в ссылке, чтобы открыть сокетное соединение с удаленным сервером.
Пожалуйста, отметьте, что с Java RMI клиент и сервер сроков может сослаться на ту же самую программу. Программа Java, которая действует как Java сервер RMI, содержит экспортируемый удаленный объект. Клиент RMI Java является программой, которая вызывает один или более методов на удаленный объект в другой виртуальной машине. Если VM выполняет обе из этих функций, он может упоминаться как клиент RMI и Java сервер RMI.
java.net.UnknownHostException?UnknownHostException. Чтобы генерировать функциональные удаленные ссылки, Java, серверы RMI должны быть в состоянии предоставить полностью определенное имя узла или IP-адрес, который разрешим от всего Java клиенты RMI (пример полностью определенного имени узла foo.bar.com). Если Java, программа RMI обеспечивает удаленную работу обратного вызова, то та программа служит Java объект RMI и следовательно, должен быть в состоянии определить разрешимое имя узла, чтобы использовать в качестве его имени узла сервера в удаленных ссылках, это передает к Java клиенты RMI. VMs, которые делают звонки в апплеты, которые служат удаленным объектам, могут бросить UnknownHostExceptions, потому что апплет был не в состоянии обеспечить применимое имя узла сервера.
Если Ваш Java приложение RMI бросает UnknownHostException, можно смотреть на получающуюся трассировку стека, чтобы видеть, является ли имя узла, которое клиент использует, чтобы связаться с его удаленным сервером, неправильным или не полностью определенное. В случае необходимости можно установить java.rmi.server.hostname свойство на сервере к корректному IP-адресу или имени узла машины сервера и Java RMI будет использовать значение этого свойства, чтобы генерировать удаленные ссылки на сервер.
UnknownHostException?java.rmi.server.hostname свойство к корректному IP-адресу Java машина сервера RMI. Можно также определить, что Ваш сервер использует полностью определенное имя узла, полученное из службы имен, устанавливая свойство:
java.rmi.server.useLocalHostname=true
java.net.InetAddress.getLocalHost() возвратить полностью определенное доменное имя. InetAddress объекты инициализированные локальные имена узлов в статическом блоке кода, выполняя обратный поиск на локальном IP-адресе, чтобы получить локальное имя узла. Однако, на машинах, которые не были соединены с сетью, это поведение, вызванное программа, чтобы зависнуть в то время как InetAddress разыскиваемый имя узла, которое не могло быть найдено. InetAddress был изменен в JDK v1.1.1, чтобы только получить [потенциально неполное] имя узла, возвращенное из собственного системного вызова, который не пытался консультироваться со службой имен. Java RMI не был изменен, чтобы компенсировать это изменение начиная со свойства java.rmi.server.hostname разрешенные пользователи, чтобы переопределить неправильные имена узлов, обеспеченные InetAddress. Java RMI, предпринятый никакая попытка консультироваться со службой имен и, мог принять значение по умолчанию к использованию неполных имен узлов. InetAddress, следующее поведение было интегрировано в новые версии JDK: RMI Java будет использовать IP-адрес или полностью определенное доменное имя, чтобы идентифицировать машину, которая служит удаленному объекту. Имена узлов сервера инициализируются к значению, полученному, выполняя следующие действия:
java.rmi.server.hostname устанавливается, Java RMI будет использовать свое значение в качестве имени узла сервера, и не будет пытаться найти полностью определенное доменное имя через любой другой метод. Это свойство имеет приоритет по всем другим средствам по обнаружению Java имя сервера RMI.java.rmi.server.useLocalHostname устанавливается в true (по умолчанию значение этого свойства false), Java RMI применяет следующую подпрограмму, чтобы получить имя узла для Java сервер RMI: InetAddress.getLocalHost().getHostName() метод содержит "." символ, тогда Java, RMI предположит, что это значение является полностью определенным доменным именем сервера и будет использовать его в качестве имени узла сервера.InetAddress.getLocalHost().getHostAddress().sun.rmi.transport.tcp.localHostnameTimeOut=timeOutMillis
java -Dsun.rmi.transport.tcp.localHostnameTimeOut=2000 MyServerApp
java.rmi.server.useLocalHostname свойство к true. Вообще, имена узлов более устойчивы чем IP-адреса. Удаленные объекты Activatable имеют тенденцию длиться дольше чем переходные удаленные объекты (например, переживая перезагрузку). Клиент RMI Java, более вероятно, определит местоположение удаленного объекта за длительный период времени, если это будет использовать квалифицированное имя узла, а не явный IP-адрес. Naming.bind и Naming.lookup необычно потребуйтесь много времени на платформах Windows?java.net.InetAddress, который будет вызывать поиски имени хоста TCP/IP - и узел отображения адресов и адресоваться к отображению имени узла ( InetAddress class делает это для соображений безопасности). На платформах Windows функции поиска выполняются собственной библиотекой сокета, таким образом, задержки происходят не в Java RMI, а в библиотеках. Если Ваш узел устанавливается, чтобы использовать DNS, то это обычно - проблема с сервером DNS, не зная об узлах, включенных в передачу, и что Вы испытываете, тайм-ауты поиска DNS. Попытайтесь определить все включенные имена узлов/адреса в локальном файле \winnt\system32\drivers\etc\hosts или \windows\hosts. Формат типичного файла узла:
IPAddress Machine Name
например:
192.0.2.61 homer
Это должно существенно сократить время, которое требуется, чтобы сделать первый поиск. 192.168.1.1). Следует тогда найти, что от DOS Shell, можно проверить с помощью ping-запросов себя (например, проверить с помощью ping-запросов
mymachine). Следует теперь быть в состоянии использовать Java RMI на машине. java.net.SocketException: Address already in use"когда я пытаюсь выполнить реестр?RegistryImpl использование (по умолчанию 1099) уже находится в использовании. Вы можете иметь другой реестр, работающий на Вашей машине, и должны будете остановить это. Если Java, RMI не в состоянии сделать нормальное (или SOCKS) соединением с намеченным сервером, и это заметит, что прокси-сервер HTTP конфигурируется, то это попытается туннелировать Java запросы RMI через тот прокси-сервер по одному.
Есть две формы туннелирования HTTP, которое попробовали в порядке. Первым является http к порту; вторым является http-to-cgi.
В туннелировании http к порту Java RMI делает попытку запроса POST HTTP к a http: URL, направленный на точное имя узла и номер порта целевого сервера. Запрос HTTP содержит единственный Java запрос RMI. Если прокси HTTP примет этот URL, то он передаст запрос POST к Java слушания сервер RMI, который распознает запрос и развернет его. Результат вызова обертывается в ответ HTTP, который возвращается через тот же самый прокси.
Часто, прокси HTTP откажутся проксировать запросы к необычным номерам портов. В этом случае Java RMI отступит к туннелированию http-to-cgi. Java запрос RMI инкапсулируется в запросе POST HTTP как прежде, но запросе URL, имеет форму http://hostname:80/cgi-bin/java-rmi.cgi?port=n (где имя узла и n являются именем узла и номером порта намеченного сервера). Должен быть сервер HTTP, слушающий на порту 80 на узле сервера, который будет работать java-rmi.cgi сценарий (предоставленный JDK), который поочередно передаст запрос к Java сервер RMI, слушающий на порту n. Java RMI может развернуть туннелированный HTTP запрос без справки от http сервера, сценария CGI, или любого другого внешнего объекта. Так, если прокси HTTP клиента может соединиться непосредственно с портом сервера, то Вы не нуждаетесь в a java-rmi.cgi сценарий вообще.
Инициировать использование туннелирования HTTP, стандартного системного свойства http.proxyHost должен быть установлен в имя узла локального прокси HTTP. (Есть отчеты, что некоторые версии Навигатора не устанавливают это свойство.)
Главный недостаток туннелирования HTTP - то, что оно не разрешает входящие вызовы или мультиплексированные соединения. Вторичный недостаток - то, что http-to-cgi метод открывает драматическую дыру в системе безопасности на стороне сервера, с тех пор без модификации это перенаправит любой входящий запрос к любому порту.
socksProxyHost должно быть, был установлен в имя узла сервера SOCKS; если номер порта сервера SOCKS не 1080, это должно быть определено в socksProxyPort свойство. Этот подход, казалось бы, был бы самым обычно полезным решением. Пока еще, ServerSockets не используйте SOCKS, таким образом, входящие вызовы должны использовать другой механизм.
Недостаток этого подхода - то, что обход брандмауэра должен быть сделан кодом, обеспеченным Java сторона сервера RMI, которая не обязательно знает, как тот обход должен быть сделан, и при этом у этого автоматически нет достаточного полномочия пересечь брандмауэр.
exportObject метод, чтобы определить точный номер порта. В JDK v1.1, сервер должен разделить на подклассы RMISocketFactory и прерывание запрашивает к createServerSocket(0), замена этого с запросом, чтобы связать с определенным номером порта. У этого подхода есть недостаток, что это требует помощи администратора сети, ответственного за локальный брандмауэр. Если экспортируемый объект выполняется в различном расположении (потому что код был загружен на тот сайт), то локальный брандмауэр может быть выполнен администраторами сети, которые не знают, кто Вы.
Идея здесь состоит в том, чтобы экспортировать объекты таким способом, которым любой вне брандмауэра, кто хочет вызвать удаленные методы на том объекте вместо этого, связывается с различным портом (возможно, на различной машине). У того различного порта есть рабочая программа, которая делает второе соединение с реальным сервером и затем качает байты каждый путь.
Хитрая часть убеждает клиент соединяться с мостом. Загружаемая фабрика сокета (JDK, v1.2 или позже) может сделать это эффективно; иначе, возможно установить java.rmi.server.hostname свойство, чтобы назвать узел моста и принять меры, чтобы номера портов были тем же самым.
Когда посторонний делает запрос к прокси, прокси сразу вперед звонок в его исходный объект на внутреннем сервере. Использование прокси прозрачно постороннему (но не к внутреннему серверу, кто должен решить, передать ли исходную ссылку или ссылку прокси когда говорящий с кем-либо).
Само собой разумеется это требует значительной установки и сотрудничества локальных администраторов сети.
В самом пессимистическом случае клиентский брандмауэр не позволяет прямых соединений TCP и имеет только прокси-сервер HTTP так, чтобы firewalled клиенты могли "бродить по сети". В этом случае Ваш узел сервера получит соединения в порту 80 содержащий Java запросы RMI, встроенные в запросы HTTP. Можно использовать сервер HTTP с java-rmi.cgi программа, или можно выполнить Java сервер RMI непосредственно на порту 80. Так или иначе сервер не может использовать объекты обратного вызова, экспортируемые клиентами..
Более оптимистический случай - то, что клиент может сделать прямые связи с сервером, но не может получить входящие соединения от сервера. В этом случае объекты обратного вызова не обычно возможны также.
Самый консервативный подход, не принимая справки от клиентских администраторов брандмауэра:
java-rmi.cgi сценарий; илиDeleGate) на порту 80, который примет соединения и сразу соединится с реальным портом сервера, чтобы передать байты назад и вперед. Это вызовет getClientHost() чтобы возвратить вводящую в заблуждение информацию, так что не делайте Реестра доступным через этот метод, если это не находится на различном узле.java-rmi.cgi сценарий, который идет с распределением JDK с сервлетом?java-rmi.cgi сценарий используя сервлет. Пример также объясняет, как выполнить удаленный объект в сервлете VM. Отметьте: Если Вы не понимаете роль это java-rmi.cgi игры в туннелирующих удаленных вызовах метода по HTTP, пожалуйста, см. вопрос о FAQ расценить HTTP, туннелирующий в Java RMI.
java.rmi.server.Unreferenced интерфейс (в дополнение к любым другим необходимым интерфейсам). Java RMI обеспечит уведомление, вызывая unreferenced метод, когда все клиенты разъединяются. Ваша реализация unreferenced метод определит, какое действие Ваш удаленный объект должен брать получение такого уведомления. Однако, если есть ссылка в реестре, то Unreferenced.unreferenced метод никогда не будут вызывать. OutOfMemoryError). Хотя API Java не определяет своевременность набора так или иначе, есть определенная причина, какой может походить на неопределенно задержанный набор удаленных объектов в JDK v1.1 реализация. Под покрытиями Java время выполнения RMI содержит слабую ссылку на экспортируемые удаленные объекты в таблице (чтобы отследить локальные так же как удаленные ссылки на объект). Единственный механизм слабой ссылки, доступный в JDK v1.1 VM, использует неагрессивную, кэширующуюся политику набора (подходящий для браузера), таким образом, объекты, которые только "слабо достижимы", не будут собраны, пока локальный GC не решает, что это действительно нуждается в той памяти, чтобы удовлетворить другое выделение. Для неактивного сервера это никогда не могло происходить. Но если память будет необходима, то серверный объект, на который нессылаются, будет собран.
Платформа SE Java включает новую инфраструктуру, что Java, который RMI будет использовать, чтобы сократить значительно количество условий, при которых происходит эта проблема.
System.exit для корректного клиентского завершения?System.exit() считается аварийным завершением, потому что оно не позволяет времени выполнения RMI отправлять соответствующие сообщения, на которые "нессылаются", серверу. Выполнение System.runFinalizersOnExit в клиенте прежде, чем завершение не достаточно, потому что не вся необходимая обработка обрабатывается в финализаторе; то есть сообщение, на которое "нессылаются", не будет отправлено серверу. (Используя "runFinalizersOnExit" является обычно опрометчивым и склонным к мертвой блокировке так или иначе.) Если Вы должны использовать System.exit() завершать клиент VM, гарантировать, что удаленные ссылки, сохраненные, в котором VM очищаются более своевременным способом, следует удостовериться, что нет никаких удаленных ссылок, все еще достижимых. Явно нулевой любые локальные ссылки, чтобы сделать их недостижимый из выполнения потоков. Это также может помочь выполнить полную сборку "мусора" и выполнить финализаторы перед выходом:
System.gc();
System.runFinalization();
unreferenced() метод тогда вызовет Java реализацией RMI (помните, что реестр является также клиентом с этой целью, так как это содержит ссылки для всей своей привязки). Если клиент содержит удаленную ссылку, она также содержит арендный договор для той ссылки, которая должна быть возобновлена (связываясь с сервером и делая a dirty() вызовите). Когда заключительный арендный договор для экспортируемого объекта истек или закрылся, объект считают нессылаемым, и (если это реализует java.rmi.Unreferenced) unreferenced() метод будет вызван.
Если у двух или больше клиентов есть ссылки на тот же самый удаленный объект, unreferenced() метод не вызовут, пока все они не истекли их арендные договоры о нем. Следовательно, если Вы используете этот метод, чтобы отследить отдельные клиенты, у каждого клиента должна быть ссылка на его собственное Unreferenced объект.
unreferenced() метод не становится вызванным до спустя десять минут после того, как я прекратил использовать удаленный объект! Как я могу сократить эту задержку?java.rmi.dgc.leaseValue, чье значение находится в миллисекундах. Установить это в более короткое время (например: 30 секунд), запустите сервер как это:
java -Djava.rmi.dgc.leaseValue=30000 ServerMain
Значение по умолчанию является 600000 миллисекунд (или 10 минутами).
Клиент возобновит каждый арендный договор, когда он на полпути истечется. Если интервал арендного договора будет слишком короток, то клиент потратит впустую много сетевой пропускной способности, напрасно возобновляющей ее арендный договор. Если интервал арендного договора будет слишком короток, то клиент будет неспособен возобновить арендный договор вовремя, и экспортируемый объект может быть удален в результате.
Будущие выпуски Java, RMI может лишить законной силы удаленные ссылки, если они не в состоянии возобновить свои арендные договоры (чтобы сохранить ссылочную целостность); недопустимо положиться на возможность использовать устарелые ссылки на удаленные объекты.
Отметьте, что необходимо только ожидать тайм-аута, если клиентская машина отказывает. Если клиент имеет некоторый контроль, когда разъединение происходит, это может отослать DGC чистый вызов быстро, делая использование Unreferenced довольно своевременный. Можно способствовать этому процессу, обнуляя любые ссылки, которые клиент может иметь к удаленному объекту и затем вызову System.gc(). (В v1.1.x Вам, вероятно, придется выполнить финализаторы синхронно и затем выполнить GC снова.)
Если или когда разрушенный клиент более поздние перезапуски и контакты сервер, сервер может вывести, что клиент потерял его состояние. Если соединение TCP считается открытое между клиентом и сервером всюду по их взаимодействию, то сервер может обнаружить клиентскую перезагрузку когда более поздняя попытка записать в сбои соединения (включая почасовый TCP keepalive пакет, если включено). Однако, Java, RMI разрабатывается, чтобы не потребовать таких постоянных соединений, поскольку это повреждает масштабируемость и не помогает очень.
Учитывая, что абсолютно невозможно немедленно определить, когда сетевая коллега отказывает или становится иначе недоступной, следует решить, как Ваше приложение должно вести себя, когда коллега прекращает отвечать.
Главные инструменты, которые Вы имеете для этой задачи, являются тайм-аутами и сбросами. После тайм-аута можно прийти к заключению, что коллега недостижима, но коллега должна знать о тайм-ауте так, чтобы это бросило пытаться достигнуть Вас. Лизинговый механизм разрабатывается, чтобы сделать это полуавтоматически.
Сброс является чисткой существующего состояния, сохраненного для коллеги. Например, клиент может вызвать сброс, когда он сначала регистрируется в его сервере, заставляя сервер отбросить любое предыдущее состояние, сохраненное для того клиента (выводившего, что клиент перезапустил без памяти предыдущего, мертвого, сеанса).
Часто, цель состоит в том, чтобы иметь и поддержать категорический список клиентов в сервере, и сохранить это актуальным без ошибки или отказа. Так как отказ и задержка могут произойти в любое время в сетевой системе, определенная степень ошибки в списке должна ожидаться. Если арендный договор или другой механизм используются, чтобы осуществить тайм-аут, то проблема утечки ресурса решается. Если бы проблема устаревших данных более серьезна - то есть, если бы это вмешалось бы в корректную работу - тогда это должно быть явно очищено в случаях, где это иначе имело бы эффект.
Например, если бизнес-объект блокируется для того, чтобы отредактировать человеком, и сеанс умирает, то блокировка должна быть повреждена так или иначе. В этом случае блокировка нуждалась бы в тайм-ауте, но если тот же самый человек сразу входит в систему и ожидает не должным быть ожидать тайм-аута, чтобы истечь, новый сеанс должен или принять блокировку или утверждать, что пользователь не содержит блокировок (позволяющий сервер безопасно уничтожить блокировку).
rmic команда в пакетном файле DOS?call перед исполнимой программой для управления, чтобы возвратиться к пакетному файлу. Например:
call rmic ClientHandler
call rmic Server
call rmic ServerHandler
call rmic Client
java.rmi.server.RemoteServer.getClientHost метод возвращает хост клиента для текущего вызова на текущем потоке. Так, невозможно передать ссылку удаленного объекта от сервера до клиента, и затем отослать это назад к серверу и быть в состоянии бросить это назад к исходной реализации class. Можно, тем не менее, использовать ссылку удаленного объекта на сервере, чтобы сделать удаленный звонок в объект.
Если Вы должны счесть реализацию class снова, Вы должны будете сохранить таблицу, которая отображает удаленную ссылку на реализацию class.
java.util.Observable и java.util.Observer с новыми интерфейсами (Вы могли вызвать их RemoteObservable и RemoteObserver). В этих новых интерфейсах сделайте каждый бросок методов java.rmi.RemoteException. Затем, Ваши удаленные объекты могут реализовать эти интерфейсы. Отметьте, что начиная с "обернутого" неудаленного объекта не расширяется java.rmi.server.UnicastRemoteObject, Вы должны будете явно экспортировать объект, используя exportObject метод UnicastRemoteObject. В выполнении этого, хотя, Вы проигрываете java.rmi.server.RemoteObject реализации equals, hashCode, и toString методы.
rmiregistry на указанном узле. Вообще, новое соединение может или не может быть создано для удаленного вызова. Соединения кэшируются Java транспорт RMI для будущего использования, так, если соединение свободно правильному месту назначения для удаленного вызова, то это используется. Клиент не может явно закрыть соединение с сервером, так как соединениями управляют в Java транспортный уровень RMI. Соединения будут время, если они будут неиспользованы сроком на время. select() вызвать. Реестр реализуется, опрашивая?LocateRegistry.getRegistry(String host) не связывается с реестром на узле, а скорее только ищет узел, чтобы удостовериться, что это существует. Так, даже при том, что этот метод успешно выполнялся, это не обязательно означает, что реестр работает на указанном узле. Это только возвращает тупик, который может тогда получить доступ к реестру. Serializable чтобы быть записанным ObjectOutputStream?java.io.Serializable интерфейс не был сделан слегка. Проект, требовавшийся баланс между потребностями разработчиков и потребностями системы быть в состоянии обеспечить предсказуемый и безопасный механизм. Самое трудное конструктивное ограничение, чтобы удовлетворить было безопасностью классов для языка программирования Java. Если классы должны были быть отмечены как являющийся сериализуемым команда разработчиков, взволнованная, что разработчик, или из забвения, лени, или из невежества не мог бы объявить class, как являющийся Serializable и затем сделайте тот class бесполезным для RMI или в целях персистентности. Мы волновались, что требование поместит в разработчика бремя знания, как class должен был использоваться другими в будущем, чрезвычайно непостижимом условии. Действительно, наш предварительный проект, как отражено в альфа-API, пришел к заключению, что случай значения по умолчанию для class должен быть то, что объекты в class сериализуемы. Мы изменили наш проект только после соображений безопасности и правильности, убежденной нас, что значение по умолчанию должно было быть то, что объект не был сериализирован.
Никакое такое ограничение не может быть сделано на объекте, как только он был сериализирован; поток байтов, который является результатом объектной сериализации, может быть считан и изменен любым объектом, у которого есть доступ к тому потоку. Это предоставляет любой объектный доступ к состоянию сериализированного объекта, который может нарушить пользователей гарантий конфиденциальности языка, ожидают. Далее, байты в потоке могут быть изменены произвольными способами, позволяя реконструкцию объекта, который никогда не создавался в пределах защит платформы Java. Есть случаи, в которых воссоздание такого объекта могло поставить под угрозу не только гарантии конфиденциальности, ожидаемые пользователями платформы Java, но целостность платформы непосредственно.
Эти нарушения не могут быть предотвращены, так как вся эта мысль о сериализации состоит в том, чтобы позволить объекту быть преобразованным в форму, которая может быть перемещена за пределами платформы Java (и поэтому за пределами гарантий конфиденциальности и целостности той среды) и затем возвращена в среду. Требование, чтобы объекты были объявлены сериализуемый, действительно означает, что разработчик class должен принять активное решение позволить возможность такого нарушения в конфиденциальности или целостности. Разработчик, который не знает о сериализации, не должен быть открытым, чтобы пойти на компромисс из-за этого отсутствия знаний. Кроме того, мы надеялись бы, что разработчик, который объявляет, что class сериализуем, делает так после некоторой мысли о возможных последствиях того объявления.
Отметьте, что этот вид проблемы безопасности не является тем, с которым может иметь дело механизм менеджера безопасности. Так как сериализация предназначается, чтобы позволить транспорт объекта от одной виртуальной машины до некоторого другого (или по пространству, поскольку это используется в RMI, или в течение долгого времени, как тогда, когда поток сохраняется к файлу), механизмы, используемые для безопасности, должны быть независимыми от среды выполнения любой определенной виртуальной машины. Мы хотели избежать в максимально возможной степени проблемы возможности сериализировать объект в одной виртуальной машине и не бывший способный десериализовывать тот объект в некоторой другой виртуальной машине. Так как менеджер безопасности является частью среды выполнения, используя менеджера безопасности для сериализации нарушил бы это требование.
Примеры легко привести. Много классов имеют дело с информацией, которая только имеет смысл в контексте времени выполнения, в котором существует определенный объект; примеры такой информации включают дескрипторы файлов, открытые сокетные соединения, информацию о безопасности, и т.д. С такими данными можно иметь дело легко, просто объявляя поля как transient, но такое объявление только необходимо, если объект собирается быть сериализированным. Новичок (или забывчивый, или поспешил) программист мог бы забыть отмечать поля как transient почти таким же способом он или она мог бы забыть отмечать class как реализацию Serializable интерфейс. Такой случай не должен привести к неправильному поведению; способ избежать этого не состоит в том, чтобы сериализировать объекты, не отмеченные как реализация Serializable.
Другим примером этого вида является "простой" объект, который является корнем графика, который охватывает большое количество объектов. Сериализация такого объекта могла привести к сериализации большого количества других, начиная с работ сериализации по всему графику. Выполнение чего-то вроде этого должно быть сознательным решением, не тем, которое происходит по умолчанию.
Потребность в этом виде мысли была приведена домой нам в группе, когда мы проходили через основной API Java библиотеки class, отмечая системные классы как сериализуемый (где необходимо). Мы первоначально думали, что это будет довольно простым процессом, и что большинство системных классов могло только быть отмечено как реализация Serializable и затем используйте реализацию по умолчанию без других изменений. То, что мы нашли, было то, что это было намного менее часто случаем, чем мы подозревали. В большом количестве классов осторожная мысль должна была быть дана тому, должно ли поле быть отмечено как transient или ли имело смысл сериализировать class вообще.
Конечно, нет никакого способа гарантировать, что разработчик программиста или class фактически собирается думать об этих проблемах, отмечая class как сериализуемый. Однако, требуя, чтобы class объявил себя как реализация Serializable интерфейс мы действительно требуем, чтобы некоторая мысль была дана программистом. Наличие сериализации быть состоянием по умолчанию объекта означало бы, что нехватка мысли могла вызвать плохие эффекты в программе, что-то, чего общий замысел платформы Java попытался избежать.
javadoc инструмент.
Как работа вокруг, следует сначала удалить высокоуровневый виджет из его контейнера (таким образом, виджеты больше не "живы"). Коллеги отбрасываются в этой точке, и Вы сохраните только состояние виджета AWT. Когда Вы позже десериализовываете и читаете, виджеты въезжают задним ходом, добавляют высокоуровневый виджет к фрейму, чтобы заставить виджеты AWT появиться. Вы, возможно, должны добавить a show вызвать.
В JDK v1.1 и позже, виджеты AWT сериализуемы. java.awt.Component Реализации class Serializable.
Использование RMI листового шифрования сериализации и дешифрование к более низкому сетевому транспорту. Мы ожидаем, что, когда безопасный канал необходим, сетевые соединения будут сделаны, используя SSL и т.п. (см. Используя RMI с SSL).
Можно использовать ByteArrayInputStream и ByteArrayOutputStream объекты как промежуточное звено помещают в запись, и считайте байты в и от файла произвольного доступа и создайте ObjectInputStreams и ObjectOutputStreams от потоков байтов, чтобы транспортировать объекты. Только необходимо удостовериться, что у Вас есть весь объект в потоке байтов, или чтение/запись объекта перестанет работать.
Например, java.io.ByteArrayOutputStream может использоваться, чтобы получить байты ObjectOutputStream. От этого можно получить результат в форме байтового массива. Это поочередно может использоваться с ByteArrayInputStream как входной к ObjectInput поток.
ObjectOutputStream, но class объекта, возможно, должен быть загружен получателем, если class не уже доступен локально. Файлы самого class не сериализируются, только имена классов. Все классы должны быть в состоянии быть загруженными во время десериализации, используя нормальные механизмы загрузки class. Для апплетов это означает, что они загружаются AppletClassLoader. Нет никаких гарантий последовательности локальных объектов, которые передают к удаленному VM, так как такие объекты передают, копируя их содержание (истинная передача значением).
ObjectInputStream от ObjectOutputStream без файла промежуточный?ObjectOutputStream и ObjectInputStream работайте к/от любому потоковому объекту. Вы могли использовать a ByteArrayOutputStream и затем получите массив и вставьте его в a ByteArrayInputStream. Вы могли также использовать переданные по каналу потоковые классы также. Любой java.io class, который расширяется OutputStream и InputStream классы могут использоваться. writeObject метод и получает это использующий readObject метод. Если я тогда изменяю значение поля в объекте и отправляю это как прежде, объект что readObject возвраты метода, кажется, то же самое как первый объект и не отражают новое значение поля. Я должен испытывать это поведение?ObjectOutputStream class отслеживает каждый объект, это сериализирует и отправляет только дескриптор, если тот объект замечается снова. Это - способ, которым это имеет дело с графиками объектов. Соответствие ObjectInputStream отслеживает все объекты, которые это создало и их дескрипторы так, когда дескриптор замечается снова, это может возвратить тот же самый объект. И выходные и входные потоки сохраняют это состояние, пока они не освобождаются. Альтернативно, ObjectOutputStream class реализует a reset метод, который отбрасывает память того, что отправил объект, таким образом отправляя объект снова, сделает копию.
Трудность с потоками состоит в том, что у них есть так много состояния, которое запутанно связывается в виртуальную машину, что это является трудным или невозможным восстановить контекст где-то в другом месте. Например, сохранение стека вызовов VM недостаточно потому что, если были собственные методы, которые вызвали процедуры C, которые поочередно вызывали код для платформы Java, будет невероятное соединение конструкций языка программирования Java и указателей C, чтобы иметь дело с. Кроме того, сериализация стека подразумевала бы сериализацию любого объекта, достижимого от любой переменной стека.
Если бы поток был возобновлен в том же самом VM, то он совместно использовал бы много состояния с исходным потоком, и поэтому перестал бы работать непредсказуемыми способами, если бы оба потока работали сразу, точно так же как два потока C, пытающиеся совместно использовать стек. Когда десериализовано в отдельном VM, трудно сказать то, что могло бы произойти.
ObjectOutputStream сериализировать каждый объект. ObjectOutputStream производит OutputStream; если Ваш объект zip расширяется OutputStream class там не является никакой проблемой, сжимающей это. Вот краткий пример, который показывает, как сериализировать дерево объектов.
import java.io.*;
class tree implements java.io.Serializable {
public tree left;
public tree right;
public int id;
public int level;
private static int count = 0;
public tree(int depth) {
id = count++;
level = depth;
if (depth > 0) {
left = new tree(depth-1);
right = new tree(depth-1);
}
}
public void print(int levels) {
for (int i = 0; i < level; i++)
System.out.print(" ");
System.out.println("node " + id);
if (level <= levels && left != null)
left.print(levels);
if (level <= levels && right != null)
right.print(levels);
}
public static void main (String argv[]) {
try {
/* Create a file to write the serialized tree to. */
FileOutputStream ostream = new FileOutputStream("tree.tmp");
/* Create the output stream */
ObjectOutputStream p = new ObjectOutputStream(ostream);
/* Create a tree with three levels. */
tree base = new tree(3);
p.writeObject(base); // Write the tree to the stream.
p.flush();
ostream.close(); // close the file.
/* Open the file and set to read objects from it. */
FileInputStream istream = new FileInputStream("tree.tmp");
ObjectInputStream q = new ObjectInputStream(istream);
/* Read a tree object, and all the subtrees */
tree new_tree = (tree)q.readObject();
new_tree.print(3); // Print out the top 3 levels of the tree
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Serializable но подкласс B реализации Serializable, будут поля class A быть сериализированными, когда B будет сериализирован?Serializable объекты выписываются и восстанавливаются. Объект может быть восстановлен, только если у class A есть конструктор без аргументов, который инициализирует поля несериализуемых супертипов. Если у подкласса есть доступ к состоянию суперкласса, это может реализовать writeObject и readObject сохранить и восстановить то состояние.