Java Linux JVM Idea

Graalvm​虚拟机集成

Posted on 2021-02-09,8 min read

安装

下载地址

# 下载
wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.0.0/graalvm-ce-java11-linux-amd64-21.0.0.tar.gz
# 解压
tar -xzvf graalvm-ce-java11-linux-amd64-21.0.0.tar.gz
# 移动
cd graalvm-ce-java11-21.0.0
mkdir /usr/lib/jvm/grallvm
mv ./* /usr/lib/jvm/grallvm
# 设置环境变量
gedit /etc/profile
# 添加一下内容,注意如果配置了其他JVM需要替换
# ---- 分割符 ----
#grallvm
export PATH=${JAVA_HOME}/bin:$PATH
export JAVA_HOME=/usr/lib/jvm/grallvm
export GRAALVM_HOME=/usr/lib/jvm/grallvm
# ---- 分割符 ----

# 更新
source /etc/profile
# 输入 which java 应该看到配置好的目录了

组件

  • Grallvm自带一个名为gu的组件管理器,如果需要安装其他语言的组件可以使用其安装,包括打包为可执行文件的native-image也需要通过gu安装。
  • 由于官网被墙,需要科学上网
gu install ruby
gu install r
gu install python
gu install wasm
gu install native-image
gu install llvm-toolchain

入门使用

编写Java程序

public class Main{
    public static void main(String[] args){
        System.out.println("Hello world");

    }
}
# 编译Class文件
javac Main.java
# 打包可执行文件
native-image Main

过程如下:

gloduck@Gloduck:~/桌面$ native-image Main
[main:5260]    classlist:   1,432.60 ms,  0.96 GB
[main:5260]        (cap):     635.28 ms,  0.96 GB
[main:5260]        setup:   2,179.71 ms,  0.96 GB
[main:5260]     (clinit):     237.55 ms,  1.22 GB
[main:5260]   (typeflow):   5,621.89 ms,  1.22 GB
[main:5260]    (objects):   4,560.28 ms,  1.22 GB
[main:5260]   (features):     352.62 ms,  1.22 GB
[main:5260]     analysis:  11,099.29 ms,  1.22 GB
[main:5260]     universe:     521.04 ms,  1.72 GB
[main:5260]      (parse):   1,434.00 ms,  1.72 GB
[main:5260]     (inline):   1,278.67 ms,  1.72 GB
[main:5260]    (compile):   9,150.77 ms,  2.35 GB
[main:5260]      compile:  12,515.00 ms,  2.35 GB
[main:5260]        image:   1,146.28 ms,  2.35 GB
[main:5260]        write:     221.07 ms,  2.35 GB
[main:5260]      [total]:  29,282.69 ms,  2.35 GB

最后产生了一个文件名为main的可执行文件(我的文件名为Main.java)。

然后执行:

gloduck@Gloduck:~/桌面$ ./main
Hello world

一个Hello world打包下来有9.1M。虽然比起C之类的打包还是要大很多,不过想对于集成JRE已经很好了

注意

中途如果出现类似:

的报错,请先安装依赖。

 sudo apt install zlib1g-dev

Windows额外配置

  • 如果想在Win10打包exe文件需要额外配置。
    • vs官网下载VS:链接
    • 安装好后,安装以下扩展:
    • 找到vs安装路径\VC\Tools\MSVC\14.28.29333\bin\Hostx64\x64,将其注册到PATH环境变量(打包exe需要cl.exe)。
    • 找到VS下载的Windows Kits文件夹,添加以下环境变量LIBINCLUDE注意大写,cl.exe打包需要的依赖),然后添加以下路径:
    • 然后保留上面的两个文件夹,VS就可以卸载了。可以像我一样移动到别的地方。

集成Maven

插件路径

  • 添加依赖:

    • 注意:
      • plugin的配置中有一个mainClass属性必须指定(含有Main方法的类),否则会无法打包。
      • 如使用IDEA之类的工具,请把JDK切换为Graalvm
  • <properties>
        <graalvm.version>21.0.0</graalvm.version>
        <main.class>cn.gloduck.vertx.Main</main.class>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.graalvm.sdk</groupId>
            <artifactId>graal-sdk</artifactId>
            <version>${graalvm.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.graalvm.nativeimage</groupId>
            <artifactId>native-image-maven-plugin</artifactId>
            <version>${graalvm.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.graalvm.nativeimage</groupId>
                <artifactId>native-image-maven-plugin</artifactId>
                <version>${graalvm.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>native-image</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                </executions>
                <configuration>
                    <skip>false</skip>
                    <mainClass>cn.gloduck.vertx.Main</mainClass>
                    <imageName>example</imageName>
                    <buildArgs>
                        --no-fallback
                    </buildArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
  • 指定了MainClass后每次只需要点击Package就能打包成可执行文件了。

打包SpringBoot

注意:以下内容为摘录内容。

参考:Github

pom添加依赖:

<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>cn.gloduck.SpringBootDemo.Start</start-class>
</properties>

配置一个独立的 profile,在编译时通过 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:

<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>

Native Image对Java动态特性的处理

由于Native Image是静态分析及AOT编译,编译器不能完全准确地预估目标应用所依赖的所有动态特性。为了保证功能的完整性,GraalVM Native Image为以下四种动态特性提供了特殊处理:

  • Java Native interface (JNI)
  • Java Reflection
  • Dynamic proxy (java.lang.reflect.Proxy)
  • Class path resources (Class.getResource)

注意

  • Graal VM不支持CGLIB,只能使用JDK动态代理
  • 如果是打包SpringBoot之类的程序,可能由于某些特性不支持,出错。如:
    • 动态代理:SpringBoot默认使用的是CGLIB动态代理。目前不支持CGLIB。所以要关闭SpringBoot的动态代理。

下一篇: Java通过AOP实现接口限制→

loading...