• graalvm 编译原生java 解决反射的问题 maven配置


    由来

    之前已经采坑完成了基于maven项目的java 二进制编译,但实际上基于原生的程序,在运行时是无法进行反射的,需要单独生成配置文件

    手动配置是不可能的,所以graavm提供一个agent工具,该工具会生成整个代码中需要用到反射的配置文件,但前提是,需要你把项目打成jar包....生成配置文件之后,再编译成二进制。
    好了,编译不成功遇到问题可以来群里找我 626070845,接下来,开干

    实战

    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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
        <groupId>com.langs</groupId>
        <version>1.0-SNAPSHOT</version>
        <modelVersion>4.0.0</modelVersion>
    
        <properties>
    
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
    
        </properties>
        <artifactId>native-netty-log4j</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.8.0.M3</version>
            </dependency>
    
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.75.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.5</version>
            </dependency>
    
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.5</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
    
    
            <dependency>
                <groupId>com.ibeetl</groupId>
                <artifactId>beetl</artifactId>
                <version>3.10.0.RELEASE</version>
            </dependency>
    
    
    
        </dependencies>
    
    
        <build>
            <finalName>native-image-js</finalName>
            <plugins>
    
    
    
    
    
    
    
    <!--            <plugin>-->
    <!--                <groupId>org.apache.maven.plugins</groupId>-->
    <!--                <artifactId>maven-shade-plugin</artifactId>-->
    <!--                <version>3.2.4</version>-->
    <!--                <executions>-->
    <!--                    <execution>-->
    <!--                        <id>package-jar</id>-->
    <!--                        <phase>package</phase>-->
    <!--                        <goals>-->
    <!--                            <goal>shade</goal>-->
    <!--                        </goals>-->
    <!--                        <configuration>-->
    <!--                            <transformers>-->
    <!--                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">-->
    <!--                                    <mainClass>com.lang.Application</mainClass>-->
    <!--                                </transformer>-->
    <!--                            </transformers>-->
    <!--                        </configuration>-->
    <!--                    </execution>-->
    <!--                </executions>-->
    <!--            </plugin>-->
    
    
    
    
    
                <plugin>
                    <groupId>org.graalvm.nativeimage</groupId>
                    <artifactId>native-image-maven-plugin</artifactId>
                    <version>20.3.0</version>
    
    
    
                    <configuration>
    
    
                        <!-- imageName用于设置生成的二进制文件名称 -->
                        <imageName>${project.artifactId}</imageName>
                        <!-- mainClass用于指定main方法类路径 -->
                        <mainClass>com.lang.Application</mainClass>
                        <!-- native image 编译参数文档:https://docs.oracle.com/en/graalvm/enterprise/20/docs/reference-manual/native-image/NativeImageMavenPlugin/ -->
    
    
    
                        <buildArgs>
                            --no-fallback
    
                            --initialize-at-build-time=org.apache.log4j.PatternLayout
                            --initialize-at-build-time=org.apache.log4j.Layout
    
                            --initialize-at-build-time=org.slf4j.MDC
                            --initialize-at-build-time=org.slf4j.LoggerFactory
                            --initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder
                            --initialize-at-build-time=org.apache.log4j.helpers.Loader
                            --initialize-at-build-time=org.apache.log4j.Logger
                            --initialize-at-build-time=org.apache.log4j.helpers.LogLog
                            --initialize-at-build-time=org.apache.log4j.LogManager
                            --initialize-at-build-time=org.apache.log4j.spi.LoggingEvent
                            --initialize-at-build-time=org.slf4j.impl.Log4jLoggerFactory
                            --initialize-at-build-time=org.slf4j.impl.Log4jLoggerAdapter
                            --initialize-at-build-time=com.lang.server.handler.FarChannelHandler
                            --initialize-at-build-time=java.beans.Introspector
                            --initialize-at-build-time=com.sun.beans.introspect.ClassInfo
    
                            --initialize-at-run-time=io.netty.channel.epoll.Epoll
                            --initialize-at-run-time=io.netty.channel.epoll.Native
                            --initialize-at-run-time=io.netty.channel.epoll.EpollEventLoop
                            --initialize-at-run-time=io.netty.channel.epoll.EpollEventArray
                            --initialize-at-run-time=io.netty.channel.DefaultFileRegion
                            --initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray
                            --initialize-at-run-time=io.netty.channel.kqueue.KQueveEventLoop
                            --initialize-at-run-time=io.netty.channel.kqueue.Native
                            --initialize-at-run-time=io.netty.channel.unix.Errors
                            --initialize-at-run-time=io.netty.channel.unix.1ovArray
                            --initialize-at-run-time=io.netty.channel.unix.Limits
                            --initialize-at-run-time=io.netty.util.internal.logging.Log4JLogger
                            --initialize-at-run-time=io.netty.channel.unix.Socket
                            --initialize-at-run-time=io.netty.channel.ChannelHandlerMask
    
                            --report-unsupported-elements-at-runtime
                            --allow-incomplete-classpath
                            --enable-url-protocols=http
                            -H:+ReportExceptionStackTraces
                            -H:EnableURLProtocols=http
                            -H:EnableURLProtocols=https
    <!--                        -H:ReflectionConfigurationFiles=E:\AAAA_CODE\new-eclipse-workspace\native-netty-log4j\reflect-config.json-->
    
                            <!--                        新增-->
    
                            <!--trace 表示编译时 进行 跟踪,有些情况下可能会报错,比如在这里设置了A类,但是A类没有MAIN方法 会导致报错-->
    <!--                        -trace-class-initialization=org.apache.log4j.PatternLayout-->
                            --trace-class-initialization=org.apache.log4j.Layout
                            --trace-class-initialization=java.beans.Introspector
                            --trace-class-initialization=com.sun.beans.introspect.ClassInfo
    
                            -Dio.netty.tryReflectionSetAccessible=true
    
                            --add-exports=java.base/java.nio=ALL-UNNAMED
    
                            --add-opens java.base/java.nio=ALL-UNNAMED
    <!--                        -language:js-->
    
    
                        </buildArgs>
    
    
    
                    </configuration>
    
    
                    <executions>
                        <execution>
                            <goals>
                                <goal>native-image</goal>
                            </goals>
                            <phase>package</phase>
                        </execution>
                    </executions>
                </plugin>
    
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>3.0.0</version>
                    <executions>
                        <execution>
                            <id>java-agent</id>
                            <goals>
                                <goal>exec</goal>
                            </goals>
                            <configuration>
                                <executable>java</executable>
                                <workingDirectory>${project.build.directory}</workingDirectory>
                                <arguments>
                                    <argument>-classpath</argument>
                                    <classpath/>
                                    <argument>com.lang.Application</argument>
                                </arguments>
                            </configuration>
    
                        </execution>
                    </executions>
                </plugin>
    
            </plugins>
        </build>
    </project>
    

    上面注释掉的plug是用于生成jar的,所以生成jar时,需要把下面编译原生的plug注释掉,把生成jar的plug放开

    直接idea上点击maven packeage 生成jar包

    生成反射配置文件(注意配置好javahome和graavm)

    不需要使用ms的控制台编译工具
    ./java -agentlib:native-image-agent=config-output-dir=E:\AAAA_CODE\new-eclipse-workspace\native-netty-log4j\src\main\resources\META-INF\native-image -jar E:\AAAA_CODE\new-eclipse-workspace\native-netty-log4j\target\native-image-js.jar

    • config-output-dir 指定反射配置文件输出的目录
    • maven项目的话,生成的配置文件必须放在resources\META-INF\native-image下

    • 可以看到,上面的指令执行后,jar会被执行一次,以便vm获取到反射信息
      E:\AAAA_CODE\new-eclipse-workspace\native-netty-log4j\src\main\resources\META-INF\native-image目录下也生成了反射配置文件

    生成二进制

    先把pom中生成jar的plug注释掉,打开生成二进制的plug
    使用ms编译工具进入到项目根目录

    执行 mvn -Pnative clean package

    • 生成二进制成功,可以看到还生成了相关需要的dll文件

    • 执行exe,启动速度非常快

    注意:由于程序没有写死循环,所以执行完就退出控制台,可以先开一个控制台,再把exe拖到这个控制台执行就行了,否则你需要在程序中写个死循环,防止程序执行完就关掉

    执行mvn -Pnative clean package 遇到的问题

    • 我遇到了万恶的should not reach here,但是也能正常生成EXE,先不管它就好。以后解决
    • 注意 由于反射时,需要用到不同的类,如果你的项目在编译二进制时 出现以下的报错提示
    --initialize-at-build-time=java.beans.Introspector
    

    --initialize-at-build-time 是指,在编译时 需要找这样的类,你只需要加到pom中即可

    参考了这些

    https://www.bookstack.cn/read/apache-dubbo-3.0-zh/917feda3752824d9.md
    https://graalvm.github.io/native-build-tools/latest/maven-plugin.html
    https://www.graalvm.org/22.1/reference-manual/native-image/Reflection/
    https://blog.csdn.net/dlz00001/article/details/107254716
    https://www.bianchengquan.com/article/223169.html

  • 相关阅读:
    docker命令总结
    VulToEs
    MYSQL
    MoonStack
    Spring mvc json null
    MySQL
    极光推送
    坑爹的RockSaw和坑爹的windows7
    App接口设计思路
    CSUOJ 1329 一行盒子(数组模拟链表)
  • 原文地址:https://www.cnblogs.com/cfas/p/16339789.html
Copyright © 2020-2023  润新知