吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2214|回复: 15
收起左侧

[Java 原创] JAVA 基于 GraalVM 构建 原生可执行文件 [SprintBoot/Java][Maven/Gradle]

[复制链接]
Vvvvvoid 发表于 2022-11-27 04:40
本帖最后由 Vvvvvoid 于 2022-11-27 04:49 编辑

前记

Java 在主导着企业级应用。但是在云中,采用 Java 的成本要比其竞争者更高。使用 GraalVM 进行原生编译降低了在云中 Java 的成本:它所创建的应用启动更快,使用的内存也更少。不过由于没有了JIT,性能并没有使用虚拟机的时候高。

环境

env.png

这里我构建了俩个项目, 一个是普通的 maven 项目, 一个是 Springboot 的 rest web 项目, 并且都支持 mvn/gradle 编译未 二进制可执行程序

JavaDemo

构建一个空的 Java 项目, 输出 Helloworld

public class Demo {
    public static void main(String[] args) {
        System.out.println("hello");
    }
}

mvn pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>java-native</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>java-native-demo</name>
    <description>Demo project for JAVA Native</description>
    <properties>
        <java.version>17</java.version>
        <!--  the version same as ../graalvm-ce-java17-22.3.0/Contents/Home/bin/native-image      -->
        <!--  https://docs.oracle.com/en/graalvm/enterprise/20/docs/reference-manual/native-image/NativeImageMavenPlugin/-->
        <graal-sdk.version>22.3.0</graal-sdk.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.graalvm.sdk</groupId>
            <artifactId>graal-sdk</artifactId>
            <version>${graal-sdk.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <!-- Run independently of the jar -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>1.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>Demo</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.graalvm.nativeimage</groupId>
                <artifactId>native-image-maven-plugin</artifactId>
                <version>21.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>native-image</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                </executions>
                <configuration>
                    <skip>false</skip>
                    <imageName>java-native</imageName>
                    <mainClass>Demo</mainClass>
                    <buildArgs>
                        --no-fallback
                    </buildArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

mvn build run

mvn package
./target/java-native

gradle cfg

settings.gradle

pluginManagement {
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
}
rootProject.name = 'java-native'
pluginManagement {
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
}
rootProject.name = 'java-native'

build.gradle

plugins {
        id 'java'
        id 'org.graalvm.buildtools.native' version '0.9.18'

}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_17

repositories {
        mavenCentral()
}

dependencies {
//         implementation 'org.springframework.boot:spring-boot-starter-web'
//         testImplementation('org.springframework.boot:spring-boot-starter-test')
}

graalvmNative {
    binaries {
        main {
            // https://graalvm.github.io/native-build-tools/latest/gradle-plugin.html
            mainClass = 'Demo'
            imageName = 'java-native'
            javaLauncher = javaToolchains.launcherFor {
                languageVersion = JavaLanguageVersion.of(17)
                vendor = JvmVendorSpec.matching("GraalVM Community")
            }
        }
    }
}

gradle build run

gradle -x test clean build nativeCompile
./build/native/nativeCompile/java-native

native-image build

native-image -cp ./target/java-native-0.0.1-SNAPSHOT.jar -H:Name=helloworld -H:Class=Demo -H:+ReportUnsupportedElementsAtRuntime --allow-incomplete-classpath

Springboot

构建一个空的 Springboot 项目, 写个HelloController

package com.example.restservice;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

        private static final String template = "Hello, %s!";
        private final AtomicLong counter = new AtomicLong();

        @GetMapping("/greeting")
        public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
                return new Greeting(counter.incrementAndGet(), String.format(template, name));
        }
}

mvn pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-native-rest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-native-rest-demo</name>
    <description>Demo project for Spring Boot Native</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-native</artifactId>
            <version>0.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.springframework.experimental</groupId>
                <artifactId>spring-aot-maven-plugin</artifactId>
                <version>0.12.1</version>
                <executions>
                    <execution>
                        <id>generate</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-generate</id>
                        <goals>
                            <goal>test-generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <profiles>
        <profile>
            <id>native</id>
            <dependencies>
                <!-- Required with Maven Surefire 2.x -->
                <dependency>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>junit-platform-launcher</artifactId>
                    <scope>test</scope>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.graalvm.buildtools</groupId>
                        <artifactId>native-maven-plugin</artifactId>
                        <version>0.9.13</version>
                        <extensions>true</extensions>
                        <executions>
                            <execution>
                                <id>build-native</id>
                                <goals>
                                    <goal>build</goal>
                                </goals>
                                <phase>package</phase>
                            </execution>
                            <execution>
                                <id>test-native</id>
                                <goals>
                                    <goal>test</goal>
                                </goals>
                                <phase>test</phase>
                            </execution>
                        </executions>
                        <configuration>
                            <!-- ... -->
                        </configuration>
                    </plugin>
                    <!-- Avoid a clash between Spring Boot repackaging and native-maven-plugin -->
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <configuration>
                            <classifier>exec</classifier>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
    <repositories>
        <!-- ... -->
        <repository>
            <id>spring-release</id>
            <name>Spring release</name>
            <url>https://repo.spring.io/release</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <!-- ... -->
        <pluginRepository>
            <id>spring-release</id>
            <name>Spring release</name>
            <url>https://repo.spring.io/release</url>
        </pluginRepository>
    </pluginRepositories>
</project>

mvn build run

mvn clean -Pnative -DskipTests package
./target/spring-native-rest

gradle cfg

settings.gradle

pluginManagement {
    repositories {
        mavenCentral()
        maven { url 'https://repo.spring.io/release' }
    }
}
rootProject.name = 'spring-native-rest'

build.gradle

plugins {
        id 'org.springframework.boot' version '2.7.1'
        id 'io.spring.dependency-management' version '1.0.15.RELEASE'
        id 'org.springframework.experimental.aot' version '0.12.1'

        id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_17

repositories {
        mavenCentral()
        maven { url 'https://repo.spring.io/release' }
}

dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-web'
        testImplementation('org.springframework.boot:spring-boot-starter-test')
}

test {
    useJUnitPlatform()
}

gradle build run

gradle -x test clean build nativeCompile
./build/native/nativeCompile/spring-native-rest

测试运行

run.png
run2.png

源码:

后记

普通的maven 项目编译后大概10mb , SpringBoot 项目 编译后大概 50mb。  
可以不依赖 JDK的情况下 还是比较能接受的, 只是编译的速度略慢 !!
目前Graavm 本地化翻译还是有很多不兼容的地方。还是有很长的路要走的。
不过 至少迈出的一大步。



免费评分

参与人数 4吾爱币 +10 热心值 +4 收起 理由
wangyou186 + 1 + 1 用心讨论,共获提升!
JinxBoy + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
woyucheng + 1 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

  • · 好帖|主题: 549, 订阅: 87

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Vvvvvoid 发表于 2022-11-27 14:02
curr1997 发表于 2022-11-27 11:23
不是说性能不求行,支持也很少,比较鸡肋

还在慢慢迭代发展,不过 原生才是趋势啊。
 楼主| Vvvvvoid 发表于 2022-11-27 16:27
pt163 发表于 2022-11-27 15:18
这东西是来用替代hotspot的新虚拟机?

这东西应该是用来去掉虚拟机的
头像被屏蔽
lvruina 发表于 2022-11-27 09:27
好好学习多挣钱 发表于 2022-11-27 09:42
没有JIT是硬伤
coder1998 发表于 2022-11-27 10:00
正好在看java,過來學一手
constwm 发表于 2022-11-27 10:15
找了好久。
curr1997 发表于 2022-11-27 11:23
不是说性能不求行,支持也很少,比较鸡肋
jiangxv 发表于 2022-11-27 15:04
过来学习一下
zhoudl 发表于 2022-11-27 15:20
学习学习
baojiajun 发表于 2022-11-27 15:57
学习一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 01:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表