Архітектура мови програмування Java


Архітектура мови програмування Java

Java — об'єктно-орієнтована мова програмування, розроблена компанією Sun Microsystems (надалі придбаною компанією Oracle). Програми Java зазвичай компілюються в спеціальний байт-код, тому вони можуть працювати на будь-якій віртуальній Java-машині (JVM) незалежно від комп'ютерної архітектури. Програмне забезпечення Java дозволяє грати в мережеві ігри, спілкуватися з людьми по всьому світу, підраховувати відсотки за іпотечними кредитами та переглядати тривимірні зображення. Програми, написані мовою програмування Java та доступ до яких можна отримати з браузера, називаються аплетами. Великі компанії також використовують аплети Java для інтранет-додатків та систем електронної комерції.
Універсальність, ефективність, портативність платформ та безпека технології Java роблять цю технологію ідеальним вибором для мережевих обчислень. Від портативних комп'ютерів до центрів збору даних, від ігрових консолей до суперкомп'ютерів, що використовуються для наукових розробок, від мобільних телефонів до мережі Інтернет - Java використовується всюди!
 

RMI (Remote Method Invocation) — програмний інтерфейс виклику віддалених методів у мові Java.
Інтерфейси Java не містять коду, що виконується. RMI підтримує два класи, що реалізують той самий інтерфейс. Перший клас є реалізацією поведінки та виконується на сервері. Другий клас працює як проміжний інтерфейс для віддаленої служби та виконується на клієнтській машині. Це показано на наступній діаграмі. Клієнтська програма викликає методи проксі-об'єкта, RMI передає запит на віддалену JVM і спрямовує їх у реалізацію об'єкта. Будь-які значення, що повертаються з реалізації, передаються назад в проксі-об'єкт і потім в клієнтську програму.
RMI-додатки часто включають дві окремі програми: сервер і клієнт. Типова серверна програма створює деякі віддалені об'єкти, робить посилання на них доступними і чекає, коли клієнти викличуть методи цих віддалених об'єктів. Типова клієнтська програма отримує віддалену посилання на один або більше віддалених об'єктів на сервері, а потім викликає їх методи. RMI забезпечує механізм, з якого сервер і клієнт зв'язуються і передають інформацію туди й назад. Таку програму іноді називають розподіленим об'єктним додатком.Однією з центральних та унікальних можливостей RMI є його здатність "завантажувати" байткод (або просто код) класу об'єкта, якщо клас не визначений у віртуальній машині одержувача. Типи та поведінка об'єкта, раніше доступного тільки на віртуальній машині сервера, може бути перекачано на іншу, можливо, віддалену віртуальну машину. RMI передає об'єкти за їх дійсним типом, так що поведінка таких об'єктів не змінюється, коли вони посилаються на іншу віртуальну машину. Це дозволяє новим типам бути введеним на віддаленій віртуальній машині, що динамічно розширює поведінку програми. Обчислювач, що є прикладом у цьому розділі, використовує здатність RMI вводити нову поведінку до розподіленої програми.

Архітектура мови програмування Java

Java – об'єктно-орієнтована мова

Архітектура RMI заснована на одному важливому принципі: визначення поведінки та реалізація цієї поведінки вважаються різними поняттями. RMI дає можливість розділити та виконати на різних JVM код, що визначає поведінку, та код, що реалізує поведінку.
Це чудово відповідає вимогам розподілених систем, де клієнти знають про визначення служб, а сервери надають ці служби.
Саме RMI визначення віддаленої служби кодується з допомогою інтерфейсу Java. Реалізація віддаленої служби кодується у класі. Таким чином, ключ до розуміння RMI пам'ятати, що інтерфейси визначають поведінку, а класи визначають реалізацію.
Мова Java — і компілювана, і інтерпретована.
Строго кажучи, Java - це мова, що інтерпретується, хоча на практиці він і інтерпретується, і компілюється. Фактично лише близько 20% Java-коду інтерпретується браузером, проте це найвідповідальніші ділянки коду. Засоби безпеки мови Java та її можливості роботи на багатьох платформах базуються на тому факті, що остаточні етапи процесу компіляції виконуються у клієнтській частині.

Спочатку програміст компілює вихідний текст програми на Java в байт-коди, які використовуються компілятором мови. Байт-коди є двійковими і не залежать від архітектури комп'ютера (або від платформи, що не відрізняється по суті). Байт-коди - не закінчений додаток, вони інтерпретуються в середовищі виконання Java-RE (Java runtime environment): зазвичай в ролі середовища виступає браузер. Оскільки кожне середовище виконання створюється для конкретної платформи, закінчений програмний продукт працюватиме на цій платформі.

Такий підхід зручний для розробників, він означає, що Java код залишається незмінним і не залежить від того, для якої платформи код призначається або в якій системі розробляється. Можна написати та скомпілювати Java-аплет у системі UNIX і вбудувати його у свою Web-сторінку. Користувачі різних систем, що мають різні середовища, можуть звернутися до цього нового аплету. При цьому кожен користувач повинен використовувати Java-сумісний браузер, і неважливо, на чому він працює: IBM, HP або Macintosh. При використанні Java потрібно супроводжувати лише один вихідний код, що виконується на багатьох платформах. Достатньо один раз скомпілювати програму для того, щоб вона працювала у різних системах.

Оскільки байт-коди Java інтерпретуються, потрібно врахувати, що Web-сторінки, що мають аплети, часто завантажуються набагато довше. Ці витрати часу пояснюються тим, що байт-коди аплетів або автономних програм містять більше даних, необхідних під час компіляції, ніж зазвичай потрібно в програмах, що не інтерпретуються. Байт-коди завантажуються в клієнтську систему подібно до того, як завантажуються HTML-коди або зображення, що становлять Web-сторінку. Потім оперативно перевіряється безпека чи надійність аплета. Перенесення мови Java досягається ціною зниження продуктивності, яке може виявитися дуже суттєвим.

Цей недолік подолано в J IT-компіляторах (Just-in-Time - "своєчасний"). JIT-компілятор транслює методи Java у машинно-залежний код для використовуваної платформи. Без такого транслятора методи не перетворюються на машинно-залежний код, а залишаються у вигляді вихідних машинно-незалежних байт-кодів, які інтерпретуються на будь-якій платформі віртуальною машиною Java. Java-додатки переносяться, а сам JIT-компілятор не може бути переносимим, оскільки він генерує машинно-залежний код для конкретної платформи аналогічно тому, як для кожної нової платформи потрібна інша версія операційної системи. В даний час браузери Mozilla Firefox та Microsoft Internet Explorer 10 використовують JIT-компілятори.

Чому така комбінація методів компіляції та інтерпретації є гідністю? Вона забезпечує захищеність та стійкість. Середовище виконання Java має елемент, званий компонувальником (linker), який перевіряє дані, що надходять у комп'ютер, і визначає, чи вони містять потенційно небезпечні файли (захищеність) чи файли, здатні викликати збій у роботі комп'ютера (стійкість).
Мова Java є об'єктно-орієнтованою і, отже, відноситься до групи мов, що розглядають дані як об'єкти та методи, що використовуються для цих об'єктів. Як згадувалося, мови Java і З++ мають у своїй основі безліч однакових принципів; вони відрізняються лише стилем та структурою.

Простіше кажучи, мови об'єктно-орієнтованого програмування (ООП) описують взаємодії між об'єктами даних. Багато мов ОВП підтримують множинне спадкування, яке іноді призводить до неоднозначності та непотрібних ускладнень. У мові Java ця можливість відсутня і підтримується лише просте спадкування. Це означає, що кожен клас в окремий час може породжуватися тільки від одного будь-якого класу. При такому підході до успадкування усуваються проблеми з класом, породженим від суперечливих чи взаємовиключних класів. У мові Java можна створювати абстрактні класи, звані інтерфейсами (interface). Інтерфейси дозволяють описувати методи, які розділяються між кількома класами, не враховуючи при цьому те, як інші класи використовують ці методи.

Кожен клас, абстрактний чи конкретний, визначає поведінка об'єкта у вигляді деякого набору методів. Весь програмний код у мові Java міститься у описах класів. Методи можуть успадковуватися від одного класу до іншого, при цьому на чолі ієрархії класів знаходиться клас об'єкта, що відноситься до пакету java.lang, що міститься в Java Core API. Інтерфейс програмування Java Core API описується в останньому розділі цього розділу.

Об'єкти можуть породжуватись від будь-якої кількості інтерфейсів (або абстрактних класів). Інтерфейси в мові Java багато в чому нагадують інтерфейси Мова Опису Інтерфейсів (IDL), тому досить просто написати компілятор з мови IDL в Java.

Такий компілятор міг би використовуватися в Єдиній Архітектурі Програми-брокера Об'єктних Запитів (Common Object Request Broker Architecture, CORBA) - системі об'єктів для побудови розподілених об'єктних систем. Чи це потрібно? Так. Як інтерфейси IDL, так і система CORBA використовуються в багатьох комп'ютерних системах, і це забезпечує міжплатформну незалежність мови Java.

Для спрощення мови в об'єктно орієнтованій мові Java не всі дані є об'єктами. Булевські типи, числа та інші прості типи не є об'єктами, проте в мові є упаковані (wrapper) об'єкти для всіх простих типів. Упаковані об'єкти дозволяють успадковувати прості типи подібно до класів. Важливо пам'ятати, що Java - строга об'єктно-орієнтована мова; ніяка оголошена змінна не може бути об'єктом. С++ хоч і є мовою ОВП, проте дозволяє порушувати стиль і використовувати типи без інкапсуляції.

Об'єктно-орієнтоване проектування дозволяє створювати модулі типу plug and play - "включи-і-працюй". Об'єктні засоби мови Java у своїй більшості ті ж, що й у С++, з додаванням можливостей Objective З більш динамічного дозволу методів.

Вихідний текст Java-прогрем компілюється в байт-коди, а не в двійкові слова. Байт-коди виконуються JVM-машиною. Компілятор Java (програма javac) зчитує файли з розширенням .java, конвертує вихідний текст у байт-коди та запам'ятовує результат у файлі з розширенням .class.

JVM-машина розглядає потік байт-кодів з файлу з розширенням .class як й послідовність команд. Кожна команда складається з однобайтного коду операції {opcode), що представляє конкретну команду, що розпізнається, і одного або декількох операндів (даних, необхідних для виконання операції). Код операції визначає дії JVM-машини. Якщо для виконання операції потрібна додаткова інформація, то за кодом операції слідує операнд.
JVM-машину утворюють чотири частини:
 

Довжина адреси в JVM-машині дорівнює 32 біт. Отже, можна адресувати до 4 Гб пам'яті, що складається з окремих байтів. Кожен регістр JVM-машини зберігає одну 32-розрядну адресу. Стек, механізм складання сміття і область методів розташовуються в межах 4 Гб пам'яті, що адресується. Дане обмеження перестав бути важливим, оскільки у час персональні комп'ютери мають трохи більше 32 Мб ОЗУ. Розмір окремого методу Java обмежено 32 Кб.

Усі процесори використовують регістри. У JVM-машині для керування системним стеком задіяні такі регістри:

При розробці Java було прийнято рішення про те, щоб у мові використовувалися чотири регістри, оскільки якби цільовий процесор мав менше регістрів, то продуктивність значно знизилася б.
Стек - це область пам'яті, де зберігаються параметри в JVM-машині. Java-програма передає байт-коди JVM-машині, де для кожного методу створюється фрейм стека.
Кожен кадр містить інформацію трьох типів:

JVM-машина має ще дві області пам'яті:

На реальне розташування цих областей не накладається жодних обмежень, і це збільшує переносимість і захищеність JVM-машини. Захищеність досягається завдяки тому, що з довільному становищі цих областей хакер неспроможна перехопити покажчик пам'яті.
JVM-машина працює з такими базовими типами даних:

Безпека та віртуальна Java-машина

Програма, отримана з мережі, має викликати певну довіру користувача. Їй надаються деякі ресурси комп'ютера, інакше вона не зможе виконувати жодних корисних дій. Однак цю програму писав хтось, який не має жодних формальних зобов'язань перед користувачем. Якщо цей хтось — хакер, то отриманий код може бути потенційно небезпечною програмою з тими ж можливостями, що і локальна програма.
Чи повинен повністю ізолювати зовнішню програму від ресурсів комп'ютера? Звичайно ж ні. У такому разі код, що виконується, не зміг би зробити нічого корисного. Більш повне та ефективне вирішення проблеми безпеки можна розбити на шість етапів:

  1. Передбачити будь-які потенційно небезпечні дії та методи вторгнення.
  2. Звести будь-які небезпечні дії до мінімального набору найпростіших операцій.
  3. Побудувати середовище програмування та комп'ютерну мову, які явно забороняють мінімальний набір небезпечних операцій, і, отже, будь-які зловмисні дії.
  4. Довести логічно або, якщо можливо, показати як очевидне той факт, що мова та середовище справді захищені проти методів навмисного вторгнення.
  5. Реалізувати мову та дозволити виконуваним програмам користуватися лише цією затвердженою безпечною мовою.
     

Сценарії зовнішньої атаки можна розбити на наступні групи (список неповний): 

  1. Пошкодження або порушення цілісності даних та/або стану програми, що виконується;
  2. Збір чи копіювання конфіденційної інформації;
  3. Блокування ресурсів, внаслідок якого вони стають недоступними для законних користувачів та програм;
  4. Захоплення ресурсів та їх використання зовнішньою неавторизованою програмою;
  5. Створення нефатальних ситуацій, що знижують продуктивність, особливо у пристроях виведення;
  6. Надання прав доступу та використання їх або комп'ютера клієнта для вторгнення в інші елементи мережі.

У табл. 1.1 перераховані потенційно вразливі ресурси, а також типи впливу, які можуть бути використані стосовно них. У хорошій стратегії захисту кожному ресурсу призначається коефіцієнт ризику та розробляються методи доступу до них із боку зовнішніх програм, що виконуються.
 

Таблиця1.1 Потенційно вразливі об'єкти та типи впливу

Об'єкти Порушення цілісності Перехоплення інформації Блокування/ Зміна прав Захоплення ресурсу Нефатальні перешкоди Захоплення повноважень
Файлова система X X X X X X
Об'єкти Порушення цілісності   Перехоплення інформації Блокування/ Зміна прав  Захоплення ресурсу Нефатальні перешкоди Захоплення повноважень
Конфіденційна інформація X X X X X X
Мережа X X X X -- X
Центральний процесор X X X X -- --
Пам'ять X X X X -- --
Пристрої виведення -- X X X X --
Пристрої введення -- X X X X --
ОС, стан програм X -- X X X --

Замість розглядати всі можливі способи втручання, схема захисту в мові Java визначає вразливі об'єкти основних потенційно небезпечних операцій, що дуже близько до описаного вище підходу.
Говорячи конкретно, схема захисту мови Java розглядає такі вразливі об'єкти:
 

Перший рівень безпеки в Java - це архітектура самої мови, синтаксичні та семантичні конструкції мови. Далі структура мови Java розглядається з погляду безпеки.
Java - повноцінна об'єктно-орієнтована мова; кожна окрема структура даних (і, отже, похідна від неї) є справжнім повнофункціональним об'єктом.Те, що кожна примітивна структура даних оформлена як об'єкт, гарантує наявність усіх теоретичних переваг захисту ООП-мов у програмах, написаних на Java, включаючи їх синтаксис та семантику:
 

Класи та методи можна оголошувати як final, забороняючи цим створення підкласів і перевизначення методів. Таке оголошення перешкоджає зловмисній зміні перевіреного коду.

З метою безпеки перетворення типів (typecasting) перевіряються як статично, і динамічно; це гарантує те, що оголошений на етапі компіляції тип об'єкта точно відповідатиме типу об'єкта під час виконання, навіть якщо стосовно цього об'єкта виконувались операції перетворення типів. Контроль за перетворенням типів перешкоджає навмисній заміні типів даних.

Ймовірно, ця особливість, реалізована безпосередньо в Java, є основною гарантією безпеки. Відсутність покажчиків у Java-програмі забезпечує те, що це елементи даних мають ім'я. Кожна проста структура даних або фрагмент коду мають ідентифікатор, що дозволяє повністю їх контролювати.

Java є багатопотоковою мовою і забезпечує захищений потоковий доступ до структур даних та об'єктів. У розділі 14 потоки Java розглядаються докладно, наводяться приклади прикладних програм.

З кожним об'єктом у мові Java пов'язаний унікальний хеш-код (hashcode). Це означає, що у будь-який момент можливий моніторинг стану Java-програми.

Під час компіляції аналізуються всі механізми захисту, які існують у синтаксисі мови Java, включаючи перевірку узгодженості оголошень private та public, правильності типів та ініціалізації всіх змінних відповідно до визначених значень.
Вихідні класи Java компілюються в байт-коди. Верифікатор байт-кодів виконує безліч перевірок узгодженості та безпеки компильованого коду. При верифікації байт-кодів виконуються такі операції:
 

Класи Java описуються усередині пакетів. Імена класів пов'язані із назвами пакетів. Пакети гарантують, що код, отриманий із мережі, відрізняється від локального коду. Прийнята бібліотека класів не може помилково чи навмисно замінити локальні бібліотеки перевірених класів або перехопити їхні права, навіть якщо ці бібліотеки мають однакові імена. Це також захищає від неперевірених, випадкових взаємодій локального та прийнятого класів.

Пізніше зв'язування гарантує, що точне розташування ресурсів на етапі виконання відбувається в останній момент. Пізніше зв'язування є серйозною перешкодою на шляху зовнішніх атак завдяки спеціальним угодам, що стосуються виділення пам'яті для цих ресурсів.

За замовчуванням механізм оперативного завантаження Java-ioiaccoB служить для вибірки зазначеного класу файлу, розташованого в локальній хост-машині.
Будь-які інші способи завантаження класів, включаючи передачу через мережу, вимагають наявності відповідного класу ClassLoader. ClassLoader — це підклас стандартного класу Java ClassLoader, що має методи, які реалізують усі механізми перевірки узгодженості та захисту та запускаються для кожного класу, що знову завантажується.

З міркувань безпеки клас ClassLoader не може виконувати жодних випереджаючих дій щодо байт-кодів. Байт-коди можуть бути отримані з Java-програми, що транслюється Java-компілятором або компілятором С++, модифікованим для створення байт-кодів. Це означає, що ClassLoader запускається тільки після перевірки байт-коду, що надійшов; цей клас відповідає за створення простору імен для завантаженого коду та дозволу посилань на імена класів, адресованих в отриманому коді. У цьому кожному пакету створюються окремі простору імен.

У мовах З і З++ програміст явно розподіляє пам'ять, звільняє її й стежить над усіма покажчиками на виділену пам'ять. Найчастіше це ускладнює супровід програм і є головним джерелом помилок, що призводять до появи "висильних посилань", викликаних використанням null-покажчиків та неправильними операціями виділення та звільнення пам'яті.

У мові Java покажчики відсутні, тому програміст ні явно управляти пам'яттю. Виділення та звільнення пам'яті виконуються автоматично, структуровано і з точним дотриманням узгодження типів Для звільнення пам'яті, що не використовується, замість явних програмованих операцій застосовується механізм складання сміття (дефрагментація пам'яті). При цьому усувається можливість помилок розподілу пам'яті та потенційні проблеми з безпекою. При ручному виділенні та звільненні пам'яті можливі нелегальні операції дублювання, клонування та захоплення повноважень доступних об'єктів, а також порушення цілісності даних.Клас SecurityManager є базовим, розширюваним засобом для побудови систем безпеки та забезпечення механізмів захисту для інших компонентів мови Java, включаючи бібліотеки класів та зовнішні середовища (наприклад, Java-сумісні браузери та машинно-залежні методи). Сам клас SecurityManager не призначений для безпосереднього використання (за замовчуванням кожна з перевірок викликає певну виняткову ситуацію із захисту); це базовий клас до створення підкласів, реалізують заданий набір методів захисту.

Крім інших особливостей у класі SecurityManager є методи для розпізнавання процесів перевірки безпеки, а також методи виконання наступних перевірок:
 

Захист від встановлення додаткового завантажувачів класів ClassLoader; Можливість компонування динамічних бібліотек (використовується для машинно-залежного коду); Читання з файлу класів а Запис до файлу класів; Створення мережного з'єднання; Можливість з'єднання з деяким мережним портом; Дозвіл вхідного мережного з'єднання; Доступність деякого пакета; Додавання до пакету нового класу.

Головним джерелом небезпеки для Java-nporpaMM є Java-код, що надходить із мережі та виконується на клієнтському комп'ютері. Подібні Java-nporpaMMbi, що транспортуються, називаються аплетами. Java-аплет має чітко визначений набір можливостей та обмежень на рівні мови, особливо щодо механізмів захисту.
На аплети, що завантажуються по мережі, накладаються такі обмеження:
 

Ім'я хост-машини має бути вказане в URL-адресі тієї HTML-сторінки, яка містила тег <applet>, або задаватися в параметрі codebase тега <applet>. Числова IP-адреса хост-машини не допускається.

Перелічені суворі обмеження доступу до локальної файлової системи стосуються аплетів, що працюють у середовищі браузера Mozilla Firefox. У Appletviewer з пакета JDK 1.0 обмеження менш суворі, і користувач може визначати явно список файлів, з якими можуть працювати аплети.
Аплети можуть зчитувати деякі властивості системи за допомогою system.getProperty (string key). Аплети в Netscape 3.0 мають необмежений доступ до цих властивостей. У JDK 1.0 Appletviewer від Sun можна індивідуально контролювати доступ до кожної властивості. У табл. 1.2 перераховано інформацію, що повертається для різних значень ключа key.

Таблиця 1.2 Доступність системних змінних

Ключ Інформація, що повертається
java.version Номер версії Java
java.vendor Інформація про виробника Java-середовища
java.vendor. url URL-адреса виробника Java-середовища
java.class.version Номер версії Java-icnacca
os.name Назва операційної системи
os.arch Архітектура операційної системи
file.separator Розділювач файлів (наприклад, /)
path.separator Роздільник шляху (наприклад,:)
line.separator Розділювач рядків

У табл. 1.3 перераховані параметри, недоступні для аплетів у середовищі браузера Netscape 3.0. Програма JDK 1.0 Appletviewer та браузер HotJava дозволяють користувачеві керувати доступом до деяких із зазначених ресурсів.

Таблиця 1.3 Системні змінні, недоступні для аплетів

Ключ Інформація, що повертається
java. home Каталог інсталяції Java
java.class.path Шлях до Java-wiaccaM
user.name  Реєстраційне ім'я користувача
user.home Домашній каталог користувача
user.dir  Поточний робочий каталог користувача

Java-система завантажує аплети двома способами. Аплет може бути переданий по мережі або завантажений з локальної файлової системи. Спосіб завантаження аплета визначає надані йому можливості.
З точки зору безпеки, локальним аплетам дозволяється виконувати такі дії:
 

Інтерфейс Java API

Java Application Programming Interface (інтерфейс прикладного програмування), або Java API, - це набір класів, розроблених компанією Sun для роботи з мовою Java. Цей інтерфейс допомагає при створенні власних класів, аплетів та програм. Використовуючи вже готові класи, можна написати Java-додаток довжиною всього кілька рядків на відміну сотень програмних рядків, необхідні створення програми на З.

Класи Java API згруповані в пакети, в яких можуть бути по кілька класів та інтерфейсів. Більш того, кожен елемент може мати різні властивості, наприклад, поля і/або методи.

Хоча програми на Java можна писати, майже нічого не знаючи про Java API, кожен створюваний клас буде залежати щонайменше від одного
класу API, за винятком класу java.lang.object, що є класом для всіх інших об'єктів. Тому при проектуванні більш складних програм, що працюють із рядками, сокетами та графічними інтерфейсами, дуже важливо знати, які об'єкти вже створені та які властивості цих об'єктів.

Нижче наведено деякі наявні або розроблювані API-інтерфейси, які не входять до базового набору:

Java Media API (включаючи Java 2D, Java Media Framework [Clocks, Audio, Video, Midi], Java Share, Java Animation, Java Telephony та Java 3D)
 

В даний час Java Core API постачається з мовою Java версії 1.0.2. Ці пакети дозволяють створювати об'єкти, обов'язкові всім реалізацій Java:

Пакет java.lang складається із класів, що утворюють ядро ​​мови Java. У ньому є як базові типи даних, такі як character і integer, а й засоби обробки помилок у вигляді класів Throwable і Error. Більш того, класи SecurityManager та System надають деякі можливості управління середовищем виконання Java.
java.io

Пакет java.io служить у мові Java стандартною бібліотекою вводу/виводу. Цей пакет дозволяє створювати потоки даних та керувати ними по-різному. У ньому є як прості типи String, і складні, наприклад StreamTokenizer.
ja va. util

Пакет java.util головним чином складається з різних корисних класів, які важко зарахувати до будь-якого іншого пакету. Серед цих допоміжних класів такі:
 

java.net

Пакет java.net робить мову Java мережевим, він надає засоби зв'язку з віддаленими ресурсами, навіщо можна створювати сокети, підключатися до них чи використовувати URL-посилання. Наприклад, за допомогою цього пакета можна створити власні клієнтські та серверні програми для протоколів Telnet, Chat або FTP.

java.awt

Пакет java.awt також називають Віконний інтерфейс користувача (Abstract Window Toolkit, AWT). У ньому містяться засоби, що дозволяють створювати потужні, привабливі та зручні інтерфейси для аплетів та автономних програм. У цьому пакеті є не тільки класи, що управляють, такі як GridBagLayout, але і деякі конкретні інтерактивні засоби, наприклад, Button і TextFieid. Що ще важливіше - це клас Graphics, що надає безліч графічних можливостей, включаючи засоби для малювання фігур та виведення зображень.
java.awt.image

Пакет java.awt.image тісно пов'язаний із java.awt. У цьому пакеті містяться засоби для маніпулювання із зображеннями, що отримуються по мережі.
java.awt.peer
 

Пакет java.awt.peer — це набір інтерфейсів, які є проміжною ланкою між вашою прикладною програмою та комп'ютером, на якому ця програма виконується. Можливо, вам не знадобиться безпосередньо працювати з цим пакетом.
 

java.applet
 

Пакет java.applet найменший з усіх у даному API-інтерфейсі, проте, завдяки наявності класу Applet, він є найхарактернішим. Цей клас має безліч корисних методів, оскільки є основою для всіх аплетів і може також за допомогою інтерфейсу
 

Прикладконтексту надавати інформацію про оточення аплету.

Java Enterprise API
 

Java Enterprise API забезпечує взаємодію з корпоративними базами даних та запитними системами. За допомогою цього API-інтерфейсу корпоративні розробники можуть будувати розподілені клієнт-серверні аплети та програми на Java, що працюють у будь-яких ОС або апаратних платформах, що є в компанії.Java Database Connectivity іди JDBC (Засоби зв'язку з базами даних) - це інтерфейс доступу до стандартних SQL-базів, що забезпечує взаємодію з великою кількістю реляційних баз даних. Багато хто чув про стандарт ODBC. Компанія Sun витратила багато зусиль на те, щоб зробити мову Java сумісною з усіма сучасними комп'ютерними стандартами.

Мова Java IDL розроблена на основі специфікації OMG Interface Definition Language (Мова опису інтерфейсів) як універсальний засіб визначення інтерфейсу між об'єктом і клієнтом на різних платформах.
Java RMI — це механізм виклику віддалених методів (remote-method invocation) для рівноправних вузлів або клієнта і сервера у випадках, коли програми на обох вузлах написані Java.

Java Commerce API

Інтерфейс Java Commerce API забезпечує створення захищених комерційних та фінансових програм у мережі Web. JavaWallet є компонентом початкового рівня, він описує та реалізує клієнтську платформу для програм, що працюють з кредитними та дебетними картками та електронними платежами.

Java Server API

Інтерфейс Java Server API - це масштабована платформа, що дозволяє легко розробляти різноманітні Java-сумісні сервери Internet та intranet. Java Server API забезпечує єдиний та узгоджений доступ до сервера та адміністративних системних ресурсів. Цей API-інтерфейс потрібен тим розробникам, хто хоче швидко розробляти власні Java-сервлети - виконувані програми, що завантажуються користувачами для запуску в мережі або на серверах.

Java Media API

Java Media API дозволяє користувачам та розробникам легко та гнучко використовувати переваги численних потужних, інтерактивних засобів мережі Web. Модуль Media Framework має годинник для синхронізації та медіаплеєри для відтворення аудіо-, відео- та MIDI-файлів. Модулі 2D та 3D забезпечують розвинені засоби обробки зображень. Для створення 20-об'єктів, що рухаються і трансформуються, можна застосовувати анімацію. Модуль Java.

Share забезпечує спільне використання додатків багатьма користувачами; приклад такого додатку - колективна "біла дошка". І нарешті, модуль Telephony дозволяє інтегрувати телефон та комп'ютер. Ймовірно, найцікавіше спробувати цей модуль.

Java Security API

Java Security API - це платформа для тих розробників, хто хоче легко та надійно включити засоби захисту у свої аплети та програми. Серед коштів, що надаються: шифрування з цифровими підписами, кодування та перевірка прав на доступ.

Java Management API

Інтерфейс Java Management API має у своєму розпорядженні великий набор масштабованих Java-об'єктів і методів для побудови аплетів, які можуть керувати корпоративними мережами через Internet і intranet-мережі. Цей API був розроблений компанією SunSoft спільно з багатьма лідерами комп'ютерної індустрії, у тому числі компанії AutoTrol, Bay Networks, BGS, ВМС, Central Design Systems, Cisco Systems, Computer Associates, CompuWare, LandMark Technologies, Legato Systems, Novell, OpenVision, Platinum Technologies , Tivoli Systems та 3Com.

Java Beans API

Java Beans API - це переносний, міжплатформний набір API-інтерфейсів для програмних компонентів. Модулі Java Beans можна буде підключати до існуючих структур, наприклад компонентів Microsoft OLE/COM/Active-X, OpenDoc і Netscape LiveConnect. Кінцевий користувач зможе компонувати компоненти Java Beans за допомогою додатків. Наприклад, компонент "кнопка" може запустити створення діаграми в іншому компоненті, або компонент передачі даних в реальному часі може представлятися іншим компонентом у вигляді графіка. (На даний момент Java Beans – це кодова назва продукту для внутрішнього користування.)

Java Embedded API

Інтерфейс Java Embedded API є підмножиною Java API для вбудованих пристроїв, що повністю підтримують Java Core API. Цей інтерфейс включає мінімальний вбудований API, побудований на базі класів java.lang, java.util і, частково, java.io. Крім того, є деякі розширення для певних завдань, наприклад, для роботи в мережі та графічних інтерфейсів.

А тепер розглянемо приклад.

Приклад використання додатку RMI

Ми створимо просту віддалену службу, що реалізує програму калькулятор, і використовуватимемо її з клієнтської програми.
Комп'ютерна RMI система складається з декількох частин.

Для спрощення завдання ми будемо використовувати той самий каталог для коду як клієнта, так і сервера. При запуску клієнта і сервера з одного каталогу нам не доведеться налаштовувати HTTP або FTP сервери для доступу до файлів класів.
Якщо припустити, що RMI система вже спроектована, для її реалізації необхідно виконати наступні кроки:

  1. Написати та відкомпілювати Java‑код для інтерфейсів
  2. Написати та відкомпілювати Java-код для класів реалізації
  3. Створити файли класів заглушки та скелета із класів реалізації
  4. Написати Java-код програми хоста для віддаленого обслуговування
  5. Розробити Java-код для клієнтської програми RMI
  6. Встановити та запустити RMI-систему
     

Першим кроком є ​​написання та компілювання Java-коду для інтерфейсів служб.
Коли ви створюєте віддалений інтерфейс, ви повинні дотримуватися таких правил:

  1. Віддалений інтерфейс повинен бути загальнодоступним – public (він не може мати «доступ на рівні пакета», так само він не може бути «дружнім»). В іншому випадку клієнти будуть отримувати помилку під час спроби завантаження об'єкта, що реалізує віддалений інтерфейс.
  2. Віддалений інтерфейс має розширювати інтерфейс java.rmi. Remote.
  3. Кожен метод віддаленого інтерфейсу має оголошувати java.rmi. RemoteException у своїй пропозиції throws на додаток до будь-яких винятків, специфічних для додатка.
  4. Віддалений об'єкт, що передається як аргумент або значення, що повертається (або безпосередньо, або як до частини локального об'єкта), повинен бути оголошений як віддалений інтерфейс, а не реалізація класу.

Інтерфейс Calculator визначає всі віддалені можливості, які пропонує служба:
 

public interface Calculator
extends java.rmi. Remote {public long add (long a, long b)
throws java.rmi. RemoteException;
public long sub (long a, long b)
throws java.rmi. RemoteException;
public long mul (long a, long b)
throws java.rmi. RemoteException;
public long div (long a, long b)
throws java.rmi. RemoteException;}


Відкомпілюємо його за допомогою компілятора Java:
 

>javac Calculator.java


Тепер напишемо реалізацію віддаленої служби. Нижче наведено клас CalculatorImpl:
 

import java.rmi.*;
import java.rmi.server.*;
Public class CalculatorImpl extends UnicastRemoteObject implements
Calculator
{
public CalculatorImpl() throws java.rmi. RemoteException
{
super();
}
public long add (long a, long b)
throws java.rmi. RemoteException
{long res=a+b;
return res;
}
public long sub (long a, long b)
throws java.rmi. RemoteException
{long res=a-b;
return res;
}
public long mul (long a, long b)
throws java.rmi. RemoteException
{ long res = a * b;
return res;
}
public long div (long a, long b)
throws java.rmi. RemoteException
{
return a/b;}}


Відкомпілюємо його.
 

>javac CalculatorImpl.java


Клас реалізації використовує UnicastRemoteObject для приєднання до системи RMI. У цьому прикладі клас реалізації безпосередньо розширює UnicastRemoteObject. Це не є обов'язковою вимогою. Клас, який не розширює UnicastRemoteObject, може використовувати свій метод exportObject() для приєднання до RMI.

Якщо клас розширює UnicastRemoteObject, він повинен забезпечити конструктор, який повідомляє, що він може згенерувати об'єкт RemoteException. Якщо цей конструктор викликає метод super(), він активізує код UnicastRemoteObject, який виконує RMI-з'єднання та ініціалізацію віддаленого об'єкта.

Далі ми використовуємо компілятор RMI, rmic, для створення файлів заглушки і скелета. Компілятор запускається із зазначенням файлу класу, що реалізує віддалену службу.
>rmic CalculatorImpl

Необхідно виконати це у нашому каталозі. Після запуску rmic потрібно знайти файл Calculator_Stub. class.
Віддалені служби RMI повинні бути поміщені у процес сервера. Клас CalculatorServer є дуже простим сервером, що надає прості елементи розміщення.

import java.rmi.Naming;
public class CalculatorServer
{
public CalculatorServer ()
{
try
{
Calculator c = new CalculatorImpl();
Naming.rebind ("rmi://localhost:1099/CalculatorService", c);
}
catch (Exception e) {
System.out.println ("Trouble: " + e);
}
}
public static void main (String args[])
{System.out.println("Server start succesfull");
new CalculatorServer();
}
}
 

У цьому прикладі бачимо виклик статичного методу Naming.rebind(). Однак, цей виклик вимагає, щоб реєстрація була запущена окремим процесом на вашому комп'ютері.

Як і багато інших мережних програм, rmiregistry звертається за IP адресою машини, на якій вона встановлена, але вона також слухає порт. Якщо ви викликаєте rmiregistry як показано вище, без аргументів, буде використаний порт за промовчанням 1099. Якщо ви хочете використовувати інший порт, ви додаєте аргумент у командний рядок, який вказує порт.

Інформація про порт також повинна передаватися в команді bind(), поряд з IP адресою машини, де розміщується реєстрація. Але це може виявити проблему, якщо ви хочете перевіряти програми RMI локально. У випуску JDK 1.1.1 є ціла зв'язка проблем:

  1. localhost не працює з RMI. Тому для експериментів з RMI на одній машині необхідно використовувати ім'я машини. Щоб знайти ім'я вашої машини під керуванням 32-бітної Windows, перейдіть до панелі керування та виберіть «Network». Виберіть закладку «Identification» та перегляньте ім'я вашого комп'ютера. Реєстр імені ігнорується. (Приклад імені: "User")
  2. RMI не працює, поки ваш комп'ютер має активні TCP/IP з'єднання, навіть якщо всі ваші компоненти просто спілкуються один з одним на локальній машині. Це означає, що ви повинні з'єднатися з вашим провайдером Internet до того, як спробуєте запустити програму або будете засмучені повідомленням про помилку. Якщо ви використовуєте порт за промовчанням 1099, вам не потрібно вказувати порт, так що ви можете просто сказати:
    Naming.bind («//user/CalculatorService»,
  3. Ви можете виконати локальну перевірку, залишивши в спокої IP адресу, а використовувати лише ідентифікатор:
    Naming.bind («CalculatorService»,  Ім'я сервісу тут довільне. У даному випадку CalculatorService вибрано просто як ім'я класу, але можна назвати так, як захочете. Важливо, щоб це було унікальне ім'я реєстрації, щоб клієнт знав, коли шукатиме, що виробляє віддалені об'єкти.

Якщо ім'я вже зареєстроване, ви отримаєте AlreadyBoundException. Щоб запобігти цьому, ви завжди можете використовувати rebind() замість bind(), оскільки rebind() або додає новий елемент, або замінює існуючий.
Навіть після завершення роботи main(), ваш об'єкт залишатиметься створеним та зареєстрованим, очікуючи, що прийде клієнт та виконає запит. Поки rmiregistry залишається запущеним, і ви не викликати Naming.unbind() на вашій машині, об'єкт залишатиметься там. З цієї причини, коли ви розробляєте код, вам необхідно вивантажувати rmiregistry і перезапускати його, коли скомпілюєте нову версію вашого віддаленого об'єкта.

Вам не обов'язково запускати rmiregistry як зовнішній процес. Якщо ви знаєте, що тільки ваша програма використовує реєстрацію, ви можете завантажити її всередині вашої програми за допомогою рядка:
LocateRegistry.createRegistry(2005);

Як і раніше, 2005 – це номер порту, який ми використали у цьому прикладі. Це еквівалентно запуску rmiregistry 2005 з командного рядка, але часто цей спосіб є більш відповідним при розробці RMI коду, так як це зменшує кількість необхідних дій при запуску та зупинці реєстрації. Після того, як ви виконаєте цей код, ви можете викликати bind(), використовуючи Naming, як і раніше.
Вихідний код клієнта наступний:

import java.rmi. Naming;
import java.rmi. RemoteException;
import java.net. MalformedURLException;
import java.rmi. NotBoundException;
public class CalculatorClient
{
public static void main (String[] args)
{
try
{
Calculator c = (Calculator)
Naming.lookup ("rmi://localhost/CalculatorService");
System.out.println (c.sub (4, 3)); System.out.println (c.add (4, 5));
System.out.println (c.mul (3, 6)); System.out.println (c.div (9, 3));
}
catch (MalformedURLException murle)
{
System.out.println();
System.out.println ("MalformedURLException");
System.out.println(murle);
}
catch (RemoteException re)
{
System.out.println();
System.out.println("RemoteException");
System.out.println(re);
}
catch (NotBoundException nbe)
{
System.out.println();
System.out.println("NotBoundException");
System.out.println(nbe);
}
catch (java.lang.ArithmeticException ae)
{
System.out.println();
System.out.println("java.lang.ArithmeticException");
System.out.println(ae);
}
}
}
 

Таким чином ми створили діючу систему RMI. Навіть якщо ви запустили три консолі на тому самому комп'ютері, RMI використовує стек протоколів TCP/IP вашої мережі для взаємодії між трьома окремими JVM. Це цілком закінчена RMI-система.