публика
Заметки по кодированию, побитовые записи, будущие статьи так же будут синхронизированы с официальным аккаунтом (Coding Insight), надеюсь все обратят внимание ^_^
предисловие
Адрес гитхаба:LjyYano/Thinking_in_Java_MindMapping
В апреле 2018 года Oracle Labs анонсировала новую черную технологию:Graal VM.
Это кросс-языковая полнофункциональная виртуальная машина, усовершенствованная на базе виртуальной машины HotSpot, которую можно использовать в качестве работающей платформы для «любого языка».
Информации о Graal VM в Интернете сейчас не так много, но вам все же нужно посмотреть официальную документацию. Эта статья призвана кратко представить:
- Что такое Graal VM?
- Каковы преимущества Graal VM?
- Каковы недостатки Graal VM?
- Как работает Graal VM?
- Установите виртуальную машину Graal на macOS
- Скомпилируйте Java-приложение на основе Spring Boot в
本地应用程序
карта разума
Ниже приведен краткий обзор Graal VM.思维导图
.
Легкая для понимания статья:GraalVM: Java в эпоху микросервисов.
Что такое GraalVM
Graal VM, официально известная как «Universal VM» и «Polyglot VM», представляет собой кросс-языковую виртуальную машину с полным стеком, улучшенную на основе виртуальной машины HotSpot под слоганом «Запускайте программы быстрее в любом месте». Вы можете запустить «любой язык» на виртуальной машине Graal, в том числе:
- Языки на базе виртуальной машины Java: Java, Scala, Groovy, Kotlin и др.;
- Языки на базе LLVM: C, C++, Rust;
- Другие языки: JavaScript, Ruby, Python, R и т. д.
Graal VM может смешивать эти языки программирования без дополнительных накладных расходов, поддерживать смешивание интерфейсов и объектов друг друга на разных языках, а также поддерживать использование нативных библиотек, написанных на этих языках.
Преимущества GraalVM
Подробности смотрите в официальной документации:Почему GraalVM?
Я думаю, что самая важная особенностьAhead-of-Time Compilation
. Substrate VM — это очень маленькая среда выполнения в Graal VM версии 0.20, включая независимую обработку исключений, планирование синхронизации, управление потоками, управление памятью (сборку мусора) и компоненты доступа JNI. Substrate VM также включает в себя本地镜像的构造器
(Native Image Generator), пользователи могут создавать исполняемые файлы на основе сборочной машины через локальный конструктор образов.
Конструктор использует технологию Points-To Analysis для поиска всех доступных кодов из записи программы, предоставленной пользователем. Во время поиска он также выполнит код инициализации и сохранит инициализированную кучу в моментальный снимок кучи, когда исполняемый файл будет окончательно сгенерирован.
Substrate VM может запускаться непосредственно из целевой программы, не повторяя процесс инициализации виртуальной машины Java. Но, соответственно, также в принципе определено, что Substrate VM должна требовать, чтобы целевая программа была полностью закрыта, то есть другой независимый от времени компиляции код и библиотеки классов не могли быть динамически загружены. Основываясь на этом предположении, Substrate VM может исследовать все пространство компиляции и определить целевой метод для всех вызовов виртуальных методов с помощью статического анализа.
Адаптация Java к Native
Если раньше для одного сервиса требовалось 7*24 часа бесперебойной работы и высокая доступность одной машины, то в настоящее время очень подходят Java-сервисы. Но все Java-приложения должны работать на сотнях мегабайт JRE, что не подходит для микросервисов.
В то же время в микросервисах приложения можно разбивать в любой момент, каждое приложение не требует большого объема памяти, но его нужно быстро запускать, обновлять в любое время и может не требовать длительного запуска. Java-приложения изначально медленно запускаются и требуют достаточного прогрева для достижения высокой производительности.
Предварительная компиляция GraalVM дает решение: официально после использования GraalVm время запуска может быть увеличено в 50 раз, а память уменьшена в 5 раз.
Недостатки Graal VM
Язык Java изначально ущемлен в микросервисах, потому что Java родился под лозунгом «напиши один раз, работай где угодно». Этот слоган встроен в ДНК Java. Если вы захотите их изменить (на самом деле сравните недостатки Java с преимуществами других языков), возникнет много трудностей:
- Механизм отражения языка Java затрудняет создание исполняемых файлов во время компиляции. Поскольку интерфейс API можно вызывать динамически во время выполнения с помощью механизма отражения, они не воспринимаются во время компиляции. Если механизм отражения не будет отменен или не будет предоставлен файл конфигурации для вызова отражения во время компиляции.
- Библиотеки байт-кода ASM, CGLIB и Javassist будут генерировать и изменять байт-коды во время выполнения, которые нельзя скомпилировать в машинный код через AOT. Например, внедрение зависимостей Spring использует расширение CGLIB. Spring адаптировал GraalVM в новой версии и может закрыть CGLIB.
- Откажитесь от внутреннего заимствования самой HotSpot VM, потому что в локальном зеркале затирается даже сам HotSpot.
- Время запуска и использование памяти действительно значительно оптимизированы, но для крупномасштабных приложений, которые работают в течение длительного времени, может не быть быстрого приложения HotSpot Java.
Как работает Graal VM
Основной принцип работы Graal VM заключается в преобразовании исходного кода этих языков (например, JavaScript) или скомпилированного промежуточного формата исходного кода (например, байт-кода LLVM) в промежуточное представление (Intermediate Representation, IR), которое можно принимается Graal VM через интерпретатор. ), например, разработка интерпретатора для преобразования байт-кода, выводимого LLVM, для поддержки языков C и C ++. Этот процесс называется «специализацией программы» (специализированная, также часто называемая частичной оценкой).
Graal VM предоставляет набор инструментов Truffle для быстрого создания интерпретатора для нового языка и использует его для создания высокопроизводительного интерпретатора байт-кода LLVM под названием Sulong.
Установите виртуальную машину Graal на macOS
Другие платформы, такие как Linux и Windows, могут относиться кInstall GraalVM. Поскольку я использую macOS, в этой статье описывается, как установить Graal VM, GraalVM Community Edition на основе OpenJDK 11 на macOS.
Установить виртуальную машину Graal
GraalVM Community Edition в macOS представляет собой файл tar.gz, а каталог установки JDK:
/Library/Java/JavaVirtualMachines/<graalvm>/Contents/Home
Шаги установки для 64-разрядной версии macOS x86 следующие:
- существуетGraalVM Releases repository on GitHubнайти на
graalvm-ce-java11-darwin-amd64-20.1.0.tar.gz
скачать. - распаковать
tar -xvf graalvm-ce-java11-darwin-amd64-20.1.0.tar.gz
- переместить папку в
/Library/Java/JavaVirtualMachines
каталог (требуется sudo).
sudo mv graalvm-ce-java11-20.1.0 /Library/Java/JavaVirtualMachines
Чтобы проверить, прошла ли установка успешно, вы можете запустить команду:
/usr/libexec/java_home -V
Текущий результат:
Matching Java Virtual Machines (2):
11.0.7, x86_64: "GraalVM CE 20.1.0" /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.1.0/Contents/Home
1.8.0_201, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.1.0/Contents/Home
- Поскольку на машине может быть несколько JDK, необходимо настроить среду выполнения.
Поставить GraalVMbin
присоединение к каталогуPATH
переменные окружения.
export PATH=/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.1.0/Contents/Home/bin:$PATH
настраиватьJAVA_HOME
переменные окружения.
export JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.1.0/Contents/Home
Примечание. Возможно, потребуется изменить файл конфигурации bashc.
Установите компоненты GraalVM
Благодаря вышеперечисленным шагам основные компоненты GraalVM были установлены.Если вам нужна дополнительная поддержка таких языков, как Python и R, вам нужно использоватьgu
компоненты.
gu install ruby
gu install r
gu install python
gu install wasm
УстановитьGraalVM Native Image
, выполните команду:
gu install native-image
УстановитьLLVM toolchain
компонент, выполните команду:
gu install llvm-toolchain
Скомпилируйте Java-приложение на основе Spring Boot в собственное приложение.
Вы можете обратиться к GitHubspring-boot-graalvmПроект, в котором перечислены все проблемы, которые могут возникнуть, когда GraalVM подробно компилирует Java-приложения Spring Boot, и сравнивается запуск и компиляция Java-приложений с локально исполняемыми Java-программами.
Проект Spring Graal Native, совместно поддерживаемый Spring и Graal VM, уже предоставляет информацию о конфигурации для большинства компонентов Spring Boot (и некоторых исправлений, которые необходимо обрабатывать на уровне кода), и нам нужно просто полагаться на этот проект. Таким образом, Graal VM может получить конфигурацию отражения, динамического прокси и т. д. во время компиляции. Нам нужно только просто зависеть от проекта.
Нужно добавить зависимости в pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-graalvm-native</artifactId>
<version>0.7.1</version>
</dependency>
Указываем путь к классу запуска:
<properties>
<start-class>com.yano.workflow.WorkflowApplication</start-class>
</properties>
Настройте отдельный профиль, который передается во время компиляцииnative-image-maven-plugin
Плагин компилирует его в собственный исполняемый файл.
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>20.1.0</version>
<configuration>
<buildArgs>-J-Xmx4G -H:+TraceClassInitialization
-H:+ReportExceptionStackTraces
-Dspring.graal.remove-unused-autoconfig=true
-Dspring.graal.remove-yaml-support=true
</buildArgs>
<imageName>${project.artifactId}</imageName>
</configuration>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Плагин отсутствует в центральном репозитории Maven, нужно указать pluginRepositories и репозитории:
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
Graal VM не поддерживает CGLIB и может использовать только динамический прокси-сервер JDK, поэтому расширение bean-компонента Spring для общих классов следует отключить. Версия Spring Boot должна быть больше или равна 2.2,SpringBootApplication
Установите для параметра proxyBeanMethods значение false в аннотации.
@SpringBootApplication(proxyBeanMethods = false)
public class SpringBootHelloApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootHelloApplication.class, args);
}
}
Упакуйте проект через maven в командной строке:
mvn -Pnative clean package
Наконец, исполняемый файл можно увидеть в целевом каталоге, который составляет около 50 МБ по сравнению с 17 МБ для толстой банки.
java -jar target/spring-boot-graal-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.0.M4)
2020-04-30 15:40:21.187 INFO 40149 --- [ main] i.j.s.SpringBootHelloApplication : Starting SpringBootHelloApplication v0.0.1-SNAPSHOT on PikeBook.fritz.box with PID 40149 (/Users/jonashecht/dev/spring-boot/spring-boot-graalvm/target/spring-boot-graal-0.0.1-SNAPSHOT.jar started by jonashecht in /Users/jonashecht/dev/spring-boot/spring-boot-graalvm)
2020-04-30 15:40:21.190 INFO 40149 --- [ main] i.j.s.SpringBootHelloApplication : No active profile set, falling back to default profiles: default
2020-04-30 15:40:22.280 INFO 40149 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-04-30 15:40:22.288 INFO 40149 --- [ main] i.j.s.SpringBootHelloApplication : Started SpringBootHelloApplication in 1.47 seconds (JVM running for 1.924)
Может запускать программу прямо через командную строку, скорость запуска очень высокая. По сравнению с обычным веб-приложением Hello World время запуска составляет1.47s
,используется внутренняя память491 MB
.
Для программ Spring Boot, скомпилированных в собственный код, скорость запуска составляет0.078s
,используется внутренняя память30 MB
.
./spring-boot-graal
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot ::
2020-05-01 10:25:31.200 INFO 42231 --- [ main] i.j.s.SpringBootHelloApplication : Starting SpringBootHelloApplication on PikeBook.fritz.box with PID 42231 (/Users/jonashecht/dev/spring-boot/spring-boot-graalvm/target/native-image/spring-boot-graal started by jonashecht in /Users/jonashecht/dev/spring-boot/spring-boot-graalvm/target/native-image)
2020-05-01 10:25:31.200 INFO 42231 --- [ main] i.j.s.SpringBootHelloApplication : No active profile set, falling back to default profiles: default
2020-05-01 10:25:31.241 WARN 42231 --- [ main] io.netty.channel.DefaultChannelId : Failed to find the current process ID from ''; using a random value: 635087100
2020-05-01 10:25:31.245 INFO 42231 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-05-01 10:25:31.245 INFO 42231 --- [ main] i.j.s.SpringBootHelloApplication : Started SpringBootHelloApplication in 0.078 seconds (JVM running for 0.08)
Суммировать
- В этой статье в основном обсуждается взаимосвязь между GraalVM и Java.На GraalVM можно запускать многие языки.Пожалуйста, обратитесь кWhy GraalVM.
- Обратите внимание на конфигурацию переменной среды Graal, если конфигурация неверна, она не может быть скомпилирована, в то же время для JDK 11 требуется более высокая версия maven.
- Graal VM и GraalVM — это одно и то же, официальный сайт называется GraalVM, а в других местах — Graal VM...
- Чтобы адаптироваться к нативу, развивается и сам JDK.
- Собственное приложение Java, скомпилированное GraalVM, подходит только для одноразового запуска, краткосрочных сценариев, длительных или традиционных программ Java более эффективны.
- Адрес GitHub для этой статьи:LjyYano/Thinking_in_Java_MindMapping
публика
Заметки по кодированию, побитовые записи, будущие статьи так же будут синхронизированы с официальным аккаунтом (Coding Insight), надеюсь все обратят внимание ^_^