如何给国外网站做seo,做的新网站能用多久,wordpress主题 wdone,视频网站大数据建设GraalVM介绍
GraalVM提前将Java应用程序编译成独立与机器码二进制文件#xff08;可执行文件、动态库文件#xff09;,如windows系统中的exe文件和dll文件。与在Java虚拟机#xff08;JVM#xff09;上运行的应用程序相比#xff0c;这些二进制文件更小#xff0c;启动速…GraalVM介绍
GraalVM提前将Java应用程序编译成独立与机器码二进制文件可执行文件、动态库文件,如windows系统中的exe文件和dll文件。与在Java虚拟机JVM上运行的应用程序相比这些二进制文件更小启动速度快100倍在没有预热的情况下提供峰值性能并且使用更少的内存和CPU。
下面只介绍开发中与Graalvm相关的配置文件和扩展点Feature和Substitute机制以及maven插件配置。
1. 配置文件
1.1 动态代码配置文件
对于动态代码需要通过指定的json文件来描述其metadata这样GraalVM才能正确的编译和优化代码。如下类型
反射配置文件名reflect-config.json动态代理 配置文件名proxy-config.json资源文件, 配置文件名resource-config.jsonJNI, 配置文件名jni-config.json配置被JNI代码调用的java方法可见jni-lib模块资源序列化, 配置文件名serialization-config.jsonpredefined classes, 配置文件名predefined-classes-config.json
这些JSON文件内容格式可见github: graalvm json file schema
1.2 命令参数配置文件
graalvm推荐开发者为自己的项目提供文件名为native-image.properties的配置文件在该配置文件中可指定native-image编译分析所需要的配置在properties文件中支持如下key
Args 配置native-image命令参数如–feature指定扩展的Feature接口、–initialize-at-build-time指定编译时初始化的类。更多命令行选项见Command-line OptionsJavaArgs 配置native-image执行时的JVM参数ImageName 配置最后生成的可执行文件名称
关于native-image.properties的内容更多具体的可见文档Native Image Build Configuration
1.3 存放位置
配置文件都存放在项目jar文件的META-INF/native-image/目录下native-image会自动加载该目录下的文件。如
META-INF/
└── native-image└── native-image.properties└── reflect-config.json└── jni-config.json为了防止多个jar文件内的配置冲突graalvm推荐在META-INF/native-image/目录下新建以你项目的groupId/artifactID为子目录如
META-INF/
└── native-image└── groupID└── artifactID└── native-image.properties└── reflect-config.json└── jni-config.json2. 动态代码配置示例
2.1 反射
类所有方法都可以用于反射reflect-config.json配置如下
[{name: com.example.User,allDeclaredConstructors: true,allPublicMethods: true,allDeclaredFields: true}
]类中指定方法和字段可用于反射配置示例如下
[{name: com.example.User,fields: [{name: name}],methods: [{name: init,parameterTypes: []},{name: setName,parameterTypes: [java.lang.String]}]}
]2.2 动态代理
假设接口com.example.IPrintServic会用于动态代理proxy-config.json配置示例如下
[{interfaces: [com.example.IPrintService]}
]2.3 资源文件
假设有如下代码用于加载类路径下的资源
try(InputStream stream this.getClass().getClassLoader().getResourceAsStream(“resource_config.properties”)) {//读取资源内容
} resource-config.json配置示例如下
{resources: {includes: [{pattern: \\Qresource_config.properties\\E}]}
}说明 上面pattern属性值为正则表达式字符\Q和\E之间的内容在正则表达式中表示字面量即对其中的特殊字符进行原始匹配比如上面的.不是匹配任意字符而就是匹配字符串中的.。
2.4 类序列化
如果项目中类com.example.User使用了JDK的序列化方式则其serialization-config.json配置示例如下
[{name: com.example.User}
]2.5 JNI中调JAVA API
如果JNI代码中有调com.example.Utils类的public static int add(int,int)方法则jni-config.json配置示例如下
[
{name:com.example.Utils,methods:[{name:add,parameterTypes:[int,int] }]
}
]3. 扩展Feature接口
native-image生成可执行代码过程中会在关键步骤执行用户自定义代码而用户代码的执行是通过graalvm的Feature机制实现的开发者可以实现Feature接口来为程序设置一些特定行为比如通过编码的方式设置以上动态代码配置。
示例
示例需求 为com.example包下注解了Reflect注解的类注册反射配置
实现Feature接口
public class ReflectFeature implements Feature {Overridepublic void beforeAnalysis(BeforeAnalysisAccess access) {// 注册元数据try (ScanResult graph new ClassGraph().overrideClassLoaders(access.getApplicationClassLoader()).overrideClasspath(access.getApplicationClassPath()).enableAllInfo().acceptPackages(com.example).scan()) {graph.getClassesWithAnnotation(Reflect.class).forEach(classInfo - {Class clazz classInfo.loadClass();RuntimeReflection.register(clazz);RuntimeReflection.registerForReflectiveInstantiation(clazz); // 可通过newInstance()方法创建与allDeclaredConstructorstrue类似RuntimeReflection.register(clazz.getDeclaredFields()); // allDeclaredFieldstrue类似RuntimeReflection.register(clazz.getDeclaredMethods());// allPublicMethodstrue类似});}}
}注以上包扫描使用classgraph工具它与其它反射工具相比优势在于它是直接解析字节码来进行匹配的好处就是不用把类加载到JVM中。classgraph的maven配置如下
dependencygroupIdio.github.classgraph/groupIdartifactIdclassgraph/artifactIdversion4.8.173/version
/dependency注册自定义的com.example.feature.ReflectFeature接口 有两种方式 方式一在native-image命令行使用参数配置--featurescom.example.feature.ReflectFeature指定方式二推荐在native-image.properties文件配置内容如下 Args --featurescom.st.graalvm.feature.StepTrackFeature4. Substitute机制
Substitute替换机制使得可以在不修改源代码的前提下对运行时行为进行适配改造以保持对原API的兼容。 GraalVM本身也通过该机制对JDK API做了很多兼容性替换。
基于该机制开发者也可以根据实际需求对一些类、方法、字段甚至是构造函数在native-image编译过程中进行替换。
替换通过注解来实现native-image编译过程会扫描这些特定注解的类替换类必须为final类型命名格式推荐为Target_{原类包名}_{原类名}。 替换机制提供的注解如下 TargetClass 注解替换类其value值为被替换类 Substitute 注解替换方法被注解的方法在方法名和签名上需与目标方法一致 Alias 注解在替换字段上被注解的字段在名称和签名上需与目标字段一致 搭配**InjectAccessors**注解可拦截字段的get和set方法示例如下 Alias InjectAccessors(Target_OriginClass_Version_value.class)
private static String version;
static class Target_OriginClass_Version_value {private static String versionValue;static String getVersion() {if (versionValue null) {versionValue 44444444L_substitute;}return versionValue;}static void setVersion(String value) {System.out.println(setVersion: value);}
}搭配**RecomputeFieldValue**注解可替换字段的值示例如下 // 替换静态字段需设置isFinaltrue
Alias RecomputeFieldValue(kind Kind.FromAlias, isFinal true)
private static boolean useNative true;
// 替换字段
Alias RecomputeFieldValue(kind Kind.FromAlias)
private boolean inited true;Inject 注解在替换类的字段上该字段在被替换类中不存在需搭配RecomputeFieldValue注解示例如下
TargetClass(OriginClass.class)
public final class Target_com_example_OriginClass {// 替换并设置字段值Alias InjectAccessors(Target_OriginClass_Type_value.class)private TypeEnum type;Inject RecomputeFieldValue(kind Kind.Reset)private TypeEnum typeValue;static class Target_OriginClass_Type_value {static TypeEnum getType(Target_OriginClass receiver) {if (receiver.typeValue null) {receiver.typeValue TypeEnum.SUBSTITUTE;}return receiver.typeValue;}static void setType(Target_OriginClass receiver, TypeEnum value) {receiver.typeValue value;}}
}5. maven编译打包配置
plugingroupIdorg.graalvm.buildtools/groupIdartifactIdnative-maven-plugin/artifactIdversion0.10.2/versionextensionstrue/extensionsexecutionsexecutionidbuild-native/idgoalsgoalcompile-no-fork/goal/goalsphasepackage/phase/executionexecutionidtest-native/idgoalsgoaltest/goal/goalsphasetest/phase/execution/executionsconfigurationimageName${project.artifactId}/imageNamesharedLibraryfalse/sharedLibrarymetadataRepositoryenabledtrue/enabled/metadataRepository/configuration
/plugin6. 其它特性
创建动态库供C/C可见文档Build a Native Shared LibraryJAVA代码可以直接调动态库接口不过java代码需要经过native-image编译后才能运行创建JNI接口在之前JNI接口实现都是C/C编写使用native-image可以直接使用JAVA来编写JNI接口实现可见文档JNI Invocation API与其它语言集成包含的语言有JS/Node.js、Python、R、Ruby、WebAssembly、LLVM语言在Truffle基础上实现可见文档Embedding Languages
工具
1. 使用native-image-agent代理库生成metadata文件
如果不清楚应用中有哪些动态代码需要提供配置可以使用graalvm提供native-image-agent来跟踪代码执行情况来生成metadata文件只需要在java启动参数中加上-agentlib:native-image-agent参数即可命令示例如下
java -agentlib:native-image-agentconfig-output-dirgraalvm -jar graalvm-1.0-SNAPSHOT.jar总结
Java语言的动态特性阻碍了native-image静态分析和编译开发者需要提供相应的配置文件native-image才能完整的识别出需要静态编译的代码。Feature机制和替换机制为开发者提供了在编译期间尽可能多的控制通过native-image不仅可以把应用编译为可执行文件也可以把公共库编译为动态库供其它语言调用还可以把公共库通过JNI接口暴露给其它java程序使用。