К тому же warmup — это не только время, которое печатается в строчке «Server startup in»: туда не входит время поднятие самой JVM, что для непрогретой JVM может быть существенным и не входит время, которое потребуется, чтобы ваше приложения начало работать в полную силу: для этого надо возможно еще пособирать профиль, покомпилировать. В конце концов JIT'у не всегда хватает ресурсов, чтобы даже горячий код оптимизировать максимально эффективно. Плюс те оптимизации, что он применяет, часто спекулятивны и при небольших изменениях в окружающей среде система неожиданно может уйти в интерпретатор со всеми вытекающими.
Тема про WLS тоже совсем не понятна, каким образом АОТ-код можно запускать под управлением СП
Если имеется в виду HotSpot AOT, то на данный момент возможно запускать только AOT-код платформы. В общем же случае, для конкретного сервера приложений можно запилить специальную AOT поддержку: как он грузит классы внутри себя тоже информация известная до исполнения. Я про это собственно и рассказываю в своей презентации. Когда сервера приложений модулиризируют и код будет грузится согласно зависимостям в модулях (ссылки между классами будут разрешаться согласно зависимостям), то для таких приложений возможен AOT и в общем случае.
В современном мире микросервисов JVM даже с достаточно сложным кодом (напр. СП wildfly) стартует меньше чем за полсекунды.
Бывают довольно разные приложения, в том числе микросервисы. И если вам нужно запустить целую пачку микросервисов, то ускорение старта, скажем в два раза, может быть не лишним. То есть, если вы распилили свое приложения на микросервисы, то свою изначальную сложность из тысячей классов вы перенесли в сотни микросервисов, и издержки на старт таким образом скорее выросли, потому что для каждого микросервиса нужно поднимать отдельную JVM.
если убрать постулат про приложения из тысячи классов
Так или иначе сложность в тысячи классов остается, если у вас не HelloWorld приложение, размазаны ли эти классы по микросервисам или нет. К тому же даже HelloWorld SpringBoot приложение уже состоит из десятков тысяч классов + десятки тысяч классов самой платформы. Понятно не все эти классы грузятся на старте, но чем больше функционала нужно, в том числе микросервису, тем больше этих классов может потребоваться.
Мы хотим в сентябре/октябре запустить технический блог. Будет несколько авторов, соответственно будет некоторое разнообразие в топиках, и надеемся, что благодаря множеству авторов он будет довольно регулярным. Блог предполагается будет на английском с его переводом на русский на хабр. Я собираюсь некоторые свои выступления переработать в текст. Начну пожалуй с верификации байткода, я его начинал именно как хабропост, но потом сделал презентацию. Рассказать нам есть о чем, но посмотрим как пойдет.
На самом же слайды не наши замеры, а одного деятеля, которые он действительно провел довольно давно, 10 лет назад — http://www.stefankrause.net/wp/?p=6
Они кроме циклов хотят полный набор фич, который бы им позволил сделать свои модули поверх стандартных. Кроме циклов — это версии, небинарное представление модулей (желательно плаггэбл), ленивый резолв. И со всеми этим делами есть проблемы в OSGi, которые никто тянуть в JPMS не будет.
Основной камень преткновения даже не циклические зависимости, а версии. IBM настаивает, чтобы проблема версий адресовалась Jigsaw. На что Марк правильно парирует, что так как они адресуются в OSGi — делать нельзя. Для проблемы версий в Jigsaw ввели слои (layers), но их ease-of-use пока еще оставляет желать лучшего. Эту проблему Марк и говорит, что можно адресовать в будущем.
Но в любом случае JPMS не будет концептуально совместим c OSGi (и JBoss modules) и это собственно сильно расстраивает IBM и Red Hat. Они не смогут сделать новую версию OSGi на базе JPMS модулей, а значит OSGi придется жить вне стандартного модулярного мира.
Excelsior JET это проприетарный продукт со своими целями создания
Sun JRE/JDK до передачи в Open source тоже был проприетарный продукт, но ничего все пользовались.
Sun прекратила.
Но передала в open source.
Если мы прекратим, то нам тоже ничего не будет мешать передать проект в open source. Но пока не похоже — еще много не окученных грядок и продажи пока позволяют развивать проект дальше.
Java написана на си,.
Java не написана на Си. Java — это набор спецификаций. OpenJDK — лишь одна из реализаций и чуть ли не единственная из таких реализаций, где AOT до недавнего времени не было.
IBM сейчас выкладывает в Open source свой J9 и у Java появляется как минимум две реализации в открытом доступе, реализующие в полном объеме спецификацию. И то, и другое — Java. Говорить, что в Java нет AOT — это неверно, начиная с как минимум 2005 года.
а AOT-компиляция в нативный код позволила бы переписать джаву на джаве
Не все можно переписать на чистой Java. К примеру кто будет собирать мусор за GC, если он написан на Java. У того же IBM была JVM, существенная часть которой написана на Java. У JRockit тоже была реализация аллокаторов на Java. Ну и у нас большая часть JVM написана на Java.
А сколько надо ресурсов, чтобы скомпилировать Eclipse или JetBrains с помощью Вашего продукта?
Пару часов на современных персональных компьютерах.
А в остальном эта версия эклипса (Version: 4.2.2) работает примерно с одинаковой скоростью
(по субьективным ощущениям) в обоих вариантах.
Вот вам и ответ про AOT. Будет он в OpenJDK или нет, настоящим он будет или нет, по субъективным ощущениям в IDE существенную разницу вряд ли почувствуете. Хотя по моим субъективным ощущениям, мне кажется, что jet-скомпилированная идея реагирует пошустрее (у свинга больше слой абстракций, чем у SWT), но каждый кулик, понятно, хвалит свое болото. А померить ощущения надо еще придумать как.
Excelsior JET Standard Edition для Linux/Windows x86 сейчас абсолютно бесплатен.
включая обновления безопасности
Обновления безопасности в Oracle JRE чаще всего относятся к браузерному плагину для Java апплетов и Java Web Start. Обе технологии у нас в продукте не поддерживаются. Тем не менее мы стараемся апдейты для PSU выпускать и два раза в год гарантируем (против четырех у Oracle).
Из-за отсутствия встроенной AOT компиляции (с кешированием), существующие среды разработки написанные на java запускаются очень медленно и работают тоже не быстро
Oracle HotSpot AOT, как раз направлен на борьбу с медленным запуском. Скорость работы сейчас гораздо меньше связана с наличием/отсутствием AOT, она больше связана с ростом объема кода самих программ и связанным с этим уровнем вложенности абстракций. MS Visual Studio тоже работает не быстро, хоть и скомпилирована AOT компилятором.
Вообще Eclispe/JetBrains мы давно умеем компилировать статически и даже у нас на сайте можно найти их (несколько устаревших версий) в скомпилированном виде и скачать абсолютно бесплатно. Мы с JetBrains довольно давно ведем переговоры, чтобы они выкладывали JET-скомпилированные версии своих продуктов на сайт, но переговоры двигаются не очень быстро (а сами мы не находим ресурсов обновлять их).
Во первых, лямбды не работают на invokedynamic, а создаются через invokedynamic, а объекты анонимных классов через new AClass$1(), то есть просто new и вызов конструктора. Первое создание лямбды много дороже, чем создание экземпляра анонимного класса, потому что нужно еще породить в рантайме анонимный класс завертку для лямбды, загрузить его, а только потом создать экземпляр этого порожденного класса. В случае анонимного класса, нужно только загрузить класс и создать экземпляр (тут кстати надо еще мерить, что быстрее прочитать готовый класс с диска или породить его на лету). Во второй же раз, если у лямбды не было контекста, то лямбда-объект автоматом закэшируется в объекте CallSite инструкции invokedynamic, то есть новых объектов создаваться не будет. В случае анонимного класса, каждый раз будет создаваться новый объект, если вы сами его руками не закэшируете. Если у лямбды есть контекст, то в обоих случаях нужно создавать новый объект, и создавать его через invokedynamic будет несколько дороже, чем в случае анонимного класса (хотя со временем, после оптимизаций, может оказаться один фиг).
Что касается invokestatic vs. invokedynamic, то invokestatic самая быстрая из всех invoke* инструкций байткода, потому что не требуется никого динамического диспатча (target всегда известен) и в отличии от invokespecial, который тоже не требует динамического диспатча, не требуется передавать параметр this. Invokedynamic же в общем случае самая медленная из всех invoke* инструкций байткода, хотя она сильно зависит от методхэндла колсайта, который возвращает бутстрэп метод. Если он вернет константный колсайт invokestatic методхэндла, то после некоторых приплясываний JVM, породится идентичный код тому, как если бы вы сразу позвали метод через invokestatic.
В Java 9 придумали до фига способов, чтобы «менее тяжелые костыли» продолжали работать:
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) остается довольно много.
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. Полная анархия и хаос как раньше.
Пункт 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 от него уже не сможете.
Откуда дровишки? Версионного контроля jigsaw не предлагает.
По дизайну. У тебя просто не встанут два разных модуля с одним и тем же именем в module path — http://openjdk.java.net/projects/jigsaw/spec/sotms/#the-module-path
Пункт 2 — это плохо, а рефлексия — это хорошо.
Рефлексия сама по себе — хорошо. Но доступ к тому, что не предполагалось быть доступным — плохо. Для внешнего наблюдателя, все что не экспортирует модуль должно интерпретироваться как несуществующее. Потому, что сегодня это одно, а завтра совсем другое. В этом и есть смысл инкапсуляции.
Если имеется в виду HotSpot AOT, то на данный момент возможно запускать только AOT-код платформы. В общем же случае, для конкретного сервера приложений можно запилить специальную AOT поддержку: как он грузит классы внутри себя тоже информация известная до исполнения. Я про это собственно и рассказываю в своей презентации. Когда сервера приложений модулиризируют и код будет грузится согласно зависимостям в модулях (ссылки между классами будут разрешаться согласно зависимостям), то для таких приложений возможен AOT и в общем случае.
Бывают довольно разные приложения, в том числе микросервисы. И если вам нужно запустить целую пачку микросервисов, то ускорение старта, скажем в два раза, может быть не лишним. То есть, если вы распилили свое приложения на микросервисы, то свою изначальную сложность из тысячей классов вы перенесли в сотни микросервисов, и издержки на старт таким образом скорее выросли, потому что для каждого микросервиса нужно поднимать отдельную JVM.
Так или иначе сложность в тысячи классов остается, если у вас не HelloWorld приложение, размазаны ли эти классы по микросервисам или нет. К тому же даже HelloWorld SpringBoot приложение уже состоит из десятков тысяч классов + десятки тысяч классов самой платформы. Понятно не все эти классы грузятся на старте, но чем больше функционала нужно, в том числе микросервису, тем больше этих классов может потребоваться.
Мы хотим в сентябре/октябре запустить технический блог. Будет несколько авторов, соответственно будет некоторое разнообразие в топиках, и надеемся, что благодаря множеству авторов он будет довольно регулярным. Блог предполагается будет на английском с его переводом на русский на хабр. Я собираюсь некоторые свои выступления переработать в текст. Начну пожалуй с верификации байткода, я его начинал именно как хабропост, но потом сделал презентацию. Рассказать нам есть о чем, но посмотрим как пойдет.
Не все мои выступления представлены в списке, но покрытие докладов почти полное.
Из непокрытого:
«История одной JVM в картинках» с Виталием Михеевым на JavaDay Новосибирск 2011
«Веб 3.0. Футуристический рассказ о будущем интернета и IT», выступление на DevDay @2gis 2012 год,
«Java худеет. Спроси меня как», JavaOne Moscow 2013
«Java restart with WebFX», FOSDEM 2015
Были еще JavaDay Новосибирск 2012, CodeFest 2012, 2013, 2016, TechTalks @ NSU
Но в любом случае JPMS не будет концептуально совместим c OSGi (и JBoss modules) и это собственно сильно расстраивает IBM и Red Hat. Они не смогут сделать новую версию OSGi на базе JPMS модулей, а значит OSGi придется жить вне стандартного модулярного мира.
Sun JRE/JDK до передачи в Open source тоже был проприетарный продукт, но ничего все пользовались.
Если мы прекратим, то нам тоже ничего не будет мешать передать проект в open source. Но пока не похоже — еще много не окученных грядок и продажи пока позволяют развивать проект дальше.
Java не написана на Си. Java — это набор спецификаций. OpenJDK — лишь одна из реализаций и чуть ли не единственная из таких реализаций, где AOT до недавнего времени не было.
IBM сейчас выкладывает в Open source свой J9 и у Java появляется как минимум две реализации в открытом доступе, реализующие в полном объеме спецификацию. И то, и другое — Java. Говорить, что в Java нет AOT — это неверно, начиная с как минимум 2005 года.
Не все можно переписать на чистой Java. К примеру кто будет собирать мусор за GC, если он написан на Java. У того же IBM была JVM, существенная часть которой написана на Java. У JRockit тоже была реализация аллокаторов на Java. Ну и у нас большая часть JVM написана на Java.
Пару часов на современных персональных компьютерах.
Вот вам и ответ про AOT. Будет он в OpenJDK или нет, настоящим он будет или нет, по субъективным ощущениям в IDE существенную разницу вряд ли почувствуете. Хотя по моим субъективным ощущениям, мне кажется, что jet-скомпилированная идея реагирует пошустрее (у свинга больше слой абстракций, чем у SWT), но каждый кулик, понятно, хвалит свое болото. А померить ощущения надо еще придумать как.
Обновления безопасности в Oracle JRE чаще всего относятся к браузерному плагину для Java апплетов и Java Web Start. Обе технологии у нас в продукте не поддерживаются. Тем не менее мы стараемся апдейты для PSU выпускать и два раза в год гарантируем (против четырех у Oracle).
Oracle HotSpot AOT, как раз направлен на борьбу с медленным запуском. Скорость работы сейчас гораздо меньше связана с наличием/отсутствием AOT, она больше связана с ростом объема кода самих программ и связанным с этим уровнем вложенности абстракций. MS Visual Studio тоже работает не быстро, хоть и скомпилирована AOT компилятором.
Вообще Eclispe/JetBrains мы давно умеем компилировать статически и даже у нас на сайте можно найти их (несколько устаревших версий) в скомпилированном виде и скачать абсолютно бесплатно. Мы с JetBrains довольно давно ведем переговоры, чтобы они выкладывали JET-скомпилированные версии своих продуктов на сайт, но переговоры двигаются не очень быстро (а сами мы не находим ресурсов обновлять их).
Что касается invokestatic vs. invokedynamic, то invokestatic самая быстрая из всех invoke* инструкций байткода, потому что не требуется никого динамического диспатча (target всегда известен) и в отличии от invokespecial, который тоже не требует динамического диспатча, не требуется передавать параметр this. Invokedynamic же в общем случае самая медленная из всех invoke* инструкций байткода, хотя она сильно зависит от методхэндла колсайта, который возвращает бутстрэп метод. Если он вернет константный колсайт invokestatic методхэндла, то после некоторых приплясываний JVM, породится идентичный код тому, как если бы вы сразу позвали метод через invokestatic.
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) остается довольно много.
Здесь рассказываеется как это работает. Сухой остаток: все что модуль экспортирует доступно по reflection кому-угодно. Соответственно, чтобы JAXB работал вам нужно экспортировать свои доменные классы из модуля. Ну а так как Unnamed Module (все что в classpath) экспортирует все, то все что работает сейчас будет работать на Java 9.
Для всего этого есть «старый добрый» classpath. Можете в нем «патчтить» все что угодно, и доступаться до чего угодно. Только опять же все это тоже должно лежать в classpath. Полная анархия и хаос как раньше.
А вы думаете почему проект Jigsaw делают 10 лет и опять отложили на июль? Конечно не все так просто.
Все публичные API Java платформы, обязаны работать как прежде. В частности тот же самый JAXB. Как они этого добились — отдельный вопрос на изучение, не внекал. Сторонние API, могут пострадать и конечно страдают. Особенно, если они затачивались на что-то, что не гарантируется и никогда не гарантировалось Java платформой. sun.misc.Unsafe сообщество отстояло, но заточки могут самые разнообразные. Тот же Javassist, к примеру, все еще переводят на Java 9 (был хороший твит по этому поводу не давно).
Это можно легко поизучать. Я думаю, что с ресурсами должно быть так же. Если ресурс лежит в экспортируемом пакете — то он доступен, иначе нет.
Нет, не обходит — http://openjdk.java.net/projects/jigsaw/spec/sotms/#services
Разумеется к вам в код может прийти любой объект, в том числе принадлежащий классу, доступа к которому у вас нет. Но доступ к формальному типу этого объекта у вас есть (предку) соответсвенно вы спокойно можете общаться с ним как представителем класса, доступ к которому у вас есть. С тем же getCause() вы можете работать как с Throwable, даже если реальный класс вам не доступен. Но позвать какой-то метод не существующий в Throwable от него уже не сможете.
По дизайну. У тебя просто не встанут два разных модуля с одним и тем же именем в module path — http://openjdk.java.net/projects/jigsaw/spec/sotms/#the-module-path
Рефлексия сама по себе — хорошо. Но доступ к тому, что не предполагалось быть доступным — плохо. Для внешнего наблюдателя, все что не экспортирует модуль должно интерпретироваться как несуществующее. Потому, что сегодня это одно, а завтра совсем другое. В этом и есть смысл инкапсуляции.