Комментарии 33
Это позволит по новому распространить программу, не требуется чтобы заказчик пошел и скачал новую версию jdk, а поставлять непосредственно собранным Runtime`ом.
А что тогда делать с обновлениями безопасности? Например, вышла новая версия JRE с исправлениями серьезных ошибок, а разработчик не хочет пересобирать приложение с новой версией (например, прекратил разработку продукта). С учетом того, сколько находят дыр в JRE — это очень важный вопрос.
а разработчик не хочет пересобирать приложение с новой версией
"Перед смертью" надо разработчику оставить завещание зарелизить приложение как stand-alone модуль. Не смотрел, можно ли jmod бандл "разобрать" на составляющие модули и выдрать, собственно, уникальный код. Всё-таки, это не zip архив. Думаю, поставка приложений в виде jimage будет малораспространённым яалением.
распространяют голую JRE (ядро + java.base), остальное загружается из репозитория с проверкой обновлений.
Я бы и сам не отказался так распространять свой продукт — когда отдаешь пользователю один модуль, где только регистрируется репозиторий, а в нем уже функциональные модули.
Если же вы ставите себе stand-alone приложение, то оно как правило всегда получает полный доступ к вашему компьютеру (в лучшем случае вас предупредят, что «запуск этого приложения может причинить вред вашему компьютеру).И новые версии Java вас не спасут от этого факта. И если вы ставите приложение из сомнительных мест, то у вас всегда есть риск подхватить что-то. И Java здесь вообще не причем, это приложение может быть написано на чем угодно.
То есть обновления безопасности Java заботяться о вас как о пользователе компьютера (не разработчика) от несанкционированного доступа к вашему компьютеру посредством запуска Java кода с (подозрительных) интернет сайтов. То есть он защищает вас пользователя от разработчика. Если разработчик не хотел причинить вред вашему компьютеру и перестал ее разрабатывать, то программа сама не захочет причинить вред вашему компьютеру в будущем, обновите вы Java или нет. А если хотел, то ему ее вообще возможно проще было написать на C или ассемблере — в этом случае никакое обновление Java вас не спасет.
А если Java программа торчит в сеть и обробатывает какие-то запросы, и о чудо нашлась дыра в JRE позволяющая внедрить код в эту программу без ее ведома через посылку запроса (или получить какой-нибудь другой несанкционированный доступ), то если в этот момент разработчик прекратил разрабатывать эту программу, то я как пользователь этой программы скорей всего бы снес ее тут же, потому что точно такая же дыра может тогда обнаружится не только в JRE, но и в коде самой этой программы. И опять никакое обновление Java меня тогда не спасет.
Недавно знакомый не программист, узнав что я занимаюсь Java, пожаловался мне что Java у него постоянно моргает, просит обновится, и он не знает нужно ли ее обновлять. И знаете что я ему посоветовал? Снести Java! И это при том, что я делаю Java последнии 20 лет. Java — на десктопных компьютерах обычных пользователей со всеми ее обновлениями — это какой-то артифакт из 90-х, по моему мнению. К сожалению я разработчик и мне нужна Java на всех компьютерах, что я исспользую, для разработки. Поэтому провести чистый эксперимент — снести Java и посмотреть, потребуется ли она мне в непрограмиисткой жизни — не могу. Но я пробовал запускать специально апплеты в своих браузерах и они нигде сейчас не работают, даже аплеты-примеры с Ораклового сайта. Нужны какие-то специальные настройки, чтобы они заработали, ведомые только админам интранетов, где есть копоративный клиентский софт на Java, запускаемый из браузера или через Java Web Start. И у меня нет приложений на Java запускающихся на „дефолтной“ JRE, то есть, той которая постоянно требует обновленний. Все вменяемые разработчики клиентского софта на Java уже давно бандлят JRE вместе со своими приложениями. И опять же клиентский десктопный софт на Java все меньше и меньше пишут. А на серваках, если у вас сервер запускается на JRE, а эта JRE обновляется по клику на system tray (кем?), то я бы не назвал способ деплоя вашего приложения хорошим.
Minecraft? Ну еще есть банки, или вот тестер на сайте Nvidia тоже на java написан.
Говорят (сам не знаю), что Майнкрафт переписали в Микрософте на C++, а до этого Микрософт его распространял с забандлиной Java.
Пока не рискнули и вряд ли сделают, так как моды. + Помимо майкрософтов есть куча других лаученров, типа FTB, которые не поставляют java (не знаю, поставляют ли майки).
Интернет-банки на Java апплетах честно гояворя не видел, правда есть такие?
В Украине пока есть) Правда, некоторые предлагают альтернативы, но часть сервисом все ще на java (у ПриватБанка на java сервис создания електронных подписей).
В банке авангард подпись джава апплетом. Приходится запускать из IE11, последнего браузера из которого это еще можно сделать. А ведь считается довольно прогрессивным банком.
OSGi правда для этой цели есть давно, по его популярности нельзя сказать что желание распилисть что то на модули возникает у многих.
И еще страньше то, что эту тему старательно обходят все, говорящие о jigsaw. прямо заговор какой то.
Я вижу 2 основные фичи
- механизм отслеживания зависимостей между модулями, то есть ClassNotFoundException случится не в момент обращения к этому классу, а при старте приложения (и в другом виде). Аналогично компиляция модулей даже не начнется, если требуемых модулей нет.
- возможность поставки приложения с сабсетом JRE, а также работа приложения на уже установленном сабсете JRE.
Тема с автоматической подгрузкой стандартных недостающих модулей с вправду нераскрыта, видимо, этим будут заниматься сторонние менеджеры.
Распространять с сабсетом — да — это одна из целей. Что касается автоматической подгрузки недостающих модулей, то в подходе Jigsaw — само понятие «недостающих» нет. Все что вашему приложению нужно определяется статически на этапе компиляции и далее вы не можете распространять свое приложение без каких-то модулей, которые нужны. Если у вас приложение с плагинами, то скорей всего вам нужно будет распространять своей приложение либо с полным JRE, либо самому придумывать как доставлять куски платформы требующиеся плагину при его установке (а что нужно опять же статически известно в модульном подходе).
Никаких. Если смотреть по аналогии кто пользует OSGi, то это достаточно узкоспециализированная область контейнеров и серверов апликаций. Jigsaw не решает многих проблем, типа версионирования, динамической подгрузки/выгрузки, активации/деакцивации модуля, etc..., что уже умеет OSGi. Например, Jigsaw не умеет из коробки управлять в рантайме разными транзитивными версиями одного модуля (хотя это может быть допилено вручную).
Модульность должна широко быть принята разработчиками билд тулзов и библиотек. Я думаю, этого не случится, потому как выигрыш очень сомнительный, а зартаты огромны.
Никаких
Ну как минимум размер памяти потребляемый JVM должен сократится за счет подгрузки только необходимых классов, если я правильно понял. Для некоторых проектов, например, для моего это критично.
Классы в JVM загружаются лениво, так что footprint не поменяется.
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
10752.0 10752.0 0.0 0.0 64512.0 2580.5 172032.0 0.0 4480.0 774.0 384.0 75.8 0 0.000 0 0.000 0.000
Из интересного
MC: Metaspace capacity (kB).
MU: Metacspace utilization (kB).
CCSC: Compressed class space capacity (kB).
CCSU: Compressed class space used (kB).
То есть классы в JVM занимают около 1МБ для hello world.
По факту все и сейчас пилят свои приложения на модули, используется ли OSGi или нет: редкий проект у которого все исходники порождают единственный артефакт. А если у вашего проекта на выходе много артефактов (жаров), то welcome, you are in Modules club! Только возможно вы до сего момента этого не осознавали. А как только вы осознаете, что ваш проект уже модульный, прямо сейчас, то вам становится довольно очевидно какие плюшки вам дает Jigsaw:
1. Зависимости между вашими модулями становятся явными. По крайней мере это будет организовывать вас и ваших коллег при написании программы. Циклические зависимости запрещены — гораздо меньше возможностей плодить неконтролируемые зависимости между модулями превращая эти зависимости в спагетти. Результат — более качественная архитектура проекта.
2. У модуля появляется наконец-то инкапсуляция! Теперь никто и никогда не сможет залезть в кишочки реализации вашего модуля (в том числе через reflection), которые вы не собирались никому открывать, а потом жаловаться, что вы эту реализацию поменяли. Из-за одной этой фишечки, я бы уже рекомендовал как можно чаще использовать модульный подход в проекте. Ранее через reflection можно было достучаться до чего угодно, даже в OSGI.
3. Даже, если весь ваш проект собирается в один артефакт, то с большой вероятностью вы все равно используете внешние зависимости, aka библиотеки. Всем этим производителям библиотек рано или поздно прийдется перейти на модули. А значит бардака в этой области тоже будет меньше. К примеру не возможна будет ситуация, когда две библиотеки, которую использует ваш проект, используют какую-то третию библиотеку, но разных версий. Что сплошь и рядом встречается сейчас, порождая различные плохо диагностируемые проблемы (что собственно и называется JAR или classpath hell).
4. Да, возможность распространять приложение с сабсетом платформы — часто важно. Важно в Embedded, и когда приложение само значительно меньше чем JRE и использует лишь малую часть платформы (игры к примеру).
Ну и в завершение Jigsaw дает возможность эволюции Java платформы как таковой, не нужно держаться за всякое легаси типа CORBA, выделяя его в отдельные (опциональные) модули и идти вперед. Это не дает вам, как разработчику, никаких фич прямо сейчас, однако опосредованно это принесет вам добро в будущем.
> К примеру не возможна будет ситуация, когда две библиотеки, которую использует ваш проект, используют какую-то третию библиотеку, но разных версий.
Откуда дровишки? Версионного контроля jigsaw не предлагает.
Откуда дровишки? Версионного контроля jigsaw не предлагает.
По дизайну. У тебя просто не встанут два разных модуля с одним и тем же именем в module path — http://openjdk.java.net/projects/jigsaw/spec/sotms/#the-module-path
Пункт 2 — это плохо, а рефлексия — это хорошо.
Рефлексия сама по себе — хорошо. Но доступ к тому, что не предполагалось быть доступным — плохо. Для внешнего наблюдателя, все что не экспортирует модуль должно интерпретироваться как несуществующее. Потому, что сегодня это одно, а завтра совсем другое. В этом и есть смысл инкапсуляции.
1. Если либа лежит в classpath и костыльный код, исправляющий ее косяки, тоже, то все будет работать как прежде
2. Если вы захотели модулиризовать свое приложение и код, зависящий от либы отправить в module path, то либу вы можете спустить в module path как automatic module, который по определению экспортирует все, а значит «костыльный код» будет опять работать.
3. Если либу успели модулиризировать (добавили module-info), но косяк, исправляющийся костыльным кодом не исправили, то вы ее можете либо демодулизировать, удалив module-info ручками, либо добавив в строку запуска
-XaddExports:YourEvilModuleThatYouNeedSoMuchAndCantChangeWithoutReflectionHacks
Надо понимать, что Java 9 модули придумали не для того, чтобы вас в чем-то ограничить, а для того чтобы вы могли делать надежную архитектуру своего приложения со строгой инкапсуляцией (reliable configuration with strong encapsulation). А способов накостылять (aka smooth migration to modular architecture) остается довольно много.
Пункт 2 порождает глобальные проблемы в совместимости.
Во-первых, это должно нарушить работу кучи библиотек и API. Пример:
JAXBContext jc = JAXBContext.newInstance("com.acme.foo");
JAXBContext лежит модуле в java.xml.bind, но доменные классы в com.acme.foo. То есть классы из com.acme.foo должны быть доступны модулю java.xml.bind, даже если он не импортирует модуль com.acme.foo.
Во-вторых, не позволяет простым способом "патчить" сторонние библиотеки, просто переписав класс в том же пакете. Не понятно, возможен ли будет по желанию "полный" импорт библиотеки со всеми ее приватными классами.
В-третьих, ни слова об экспортировании ресурсов: ClassLoader.getResource(). Если ресурсы доступны только текущему модулю, то это сломает огромное количество библиотек, в том числе java.util.ServiceLoader. Кстати, тему сервисов jigsaw вообще обходит стороной, тогда как в OSGi это центральная фишка.
Ну и в-четвертых, приватные классы модулей могут вылезать наружу как содержимое других объектов. Самый простой пример: exception chain, который в getCause() будет содержать внутренний эксепшн модуля или его транзитивных зависимостей. Как будет контролироваться доступ к этим классам — не понятно.
Вобщем, вопросов много, а вразумительных ответов по тому как работает модульность в jigsaw нет.
Пункт 2 порождает глобальные проблемы в совместимости.
А вы думаете почему проект Jigsaw делают 10 лет и опять отложили на июль? Конечно не все так просто.
Во-первых, это должно нарушить работу кучи библиотек и API
Все публичные API Java платформы, обязаны работать как прежде. В частности тот же самый JAXB. Как они этого добились — отдельный вопрос на изучение, не внекал. Сторонние API, могут пострадать и конечно страдают. Особенно, если они затачивались на что-то, что не гарантируется и никогда не гарантировалось Java платформой. sun.misc.Unsafe сообщество отстояло, но заточки могут самые разнообразные. Тот же Javassist, к примеру, все еще переводят на Java 9 (был хороший твит по этому поводу не давно).
В-третьих, ни слова об экспортировании ресурсов: ClassLoader.getResource()
Это можно легко поизучать. Я думаю, что с ресурсами должно быть так же. Если ресурс лежит в экспортируемом пакете — то он доступен, иначе нет.
Кстати, тему сервисов jigsaw вообще обходит стороной,
Нет, не обходит — http://openjdk.java.net/projects/jigsaw/spec/sotms/#services
Ну и в-четвертых, приватные классы модулей могут вылезать наружу как содержимое других объектов.
Разумеется к вам в код может прийти любой объект, в том числе принадлежащий классу, доступа к которому у вас нет. Но доступ к формальному типу этого объекта у вас есть (предку) соответсвенно вы спокойно можете общаться с ним как представителем класса, доступ к которому у вас есть. С тем же getCause() вы можете работать как с Throwable, даже если реальный класс вам не доступен. Но позвать какой-то метод не существующий в Throwable от него уже не сможете.
В-третьих, ни слова об экспортировании ресурсов: ClassLoader.getResource()
Лучшее, что я нешел по теме — это саммари Марка
В частности:
All existing resource-lookup methods in Class and ClassLoader work as
they do today for resources on the class path.
- The new java.lang.reflect.Module::getResourceAsStream method can be
used to read the resources of any named module, without restriction.
Ну и в-четвертых, приватные классы модулей могут вылезать наружу как содержимое других объектов
Я, наверное, сейчас полную глупость скажу, но как это отличается от ситуации, когда мы из некого метода возвращаем объект фактического типа приватного подкласса, отнаследованного от публичного класса? Мы можем работать с этим объектом, мы вот только с приватным классом работать не можем.
Я вижу, что вы это пример на хабре приводили еще год назад, наверное что-то не понимаю.
JAXBContext лежит модуле в java.xml.bind, но доменные классы в com.acme.foo. То есть классы из com.acme.foo должны быть доступны модулю java.xml.bind, даже если он не импортирует модуль com.acme.foo.
Здесь рассказываеется как это работает. Сухой остаток: все что модуль экспортирует доступно по reflection кому-угодно. Соответственно, чтобы JAXB работал вам нужно экспортировать свои доменные классы из модуля. Ну а так как Unnamed Module (все что в classpath) экспортирует все, то все что работает сейчас будет работать на Java 9.
Во-вторых, не позволяет простым способом «патчить» сторонние библиотеки, просто переписав класс в том же пакете. Не понятно, возможен ли будет по желанию «полный» импорт библиотеки со всеми ее приватными классами.
Для всего этого есть «старый добрый» classpath. Можете в нем «патчтить» все что угодно, и доступаться до чего угодно. Только опять же все это тоже должно лежать в classpath. Полная анархия и хаос как раньше.
Проект Jigsaw в Java 9. Модулярное будущее, которого не избежать