目的:解决native-image中gson功能无效的问题。 可以通过项目的 native-image Profile 来启用: mvn -P native-image -Dmaven.test.skip=true clean source:jar install 编译时会在各包中增加2个文件: META-INF/native-image/.../reflection-config.json META-INF/native-image/.../native-image.propertiesdev1
| @@ -99,6 +99,7 @@ | |||||
| </scm> | </scm> | ||||
| <modules> | <modules> | ||||
| <module>weixin-graal</module> | |||||
| <module>weixin-java-common</module> | <module>weixin-java-common</module> | ||||
| <module>weixin-java-cp</module> | <module>weixin-java-cp</module> | ||||
| <module>weixin-java-mp</module> | <module>weixin-java-mp</module> | ||||
| @@ -331,6 +332,14 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| </profile> | </profile> | ||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| </profile> | |||||
| </profiles> | </profiles> | ||||
| <build> | <build> | ||||
| @@ -0,0 +1,40 @@ | |||||
| <?xml version="1.0"?> | |||||
| <project 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" | |||||
| xmlns="http://maven.apache.org/POM/4.0.0"> | |||||
| <modelVersion>4.0.0</modelVersion> | |||||
| <parent> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>wx-java</artifactId> | |||||
| <version>3.6.7.B</version> | |||||
| </parent> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <name>WxJava - Graal</name> | |||||
| <description>微信开发Java内部配合graal以产生native-image配置的辅助工具, 可以通过项目的 native-image Profile 来启用: mvn -P native-image ... | |||||
| </description> | |||||
| <dependencies> | |||||
| <dependency> | |||||
| <groupId>org.projectlombok</groupId> | |||||
| <artifactId>lombok</artifactId> | |||||
| <scope>compile</scope> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <proc>none</proc> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </project> | |||||
| @@ -0,0 +1,167 @@ | |||||
| package cn.binarywang.wx.graal; | |||||
| import lombok.Data; | |||||
| import javax.annotation.processing.AbstractProcessor; | |||||
| import javax.annotation.processing.RoundEnvironment; | |||||
| import javax.annotation.processing.SupportedAnnotationTypes; | |||||
| import javax.annotation.processing.SupportedSourceVersion; | |||||
| import javax.lang.model.SourceVersion; | |||||
| import javax.lang.model.element.TypeElement; | |||||
| import javax.lang.model.type.DeclaredType; | |||||
| import javax.lang.model.type.TypeKind; | |||||
| import javax.lang.model.type.TypeMirror; | |||||
| import javax.lang.model.util.ElementFilter; | |||||
| import javax.tools.FileObject; | |||||
| import javax.tools.StandardLocation; | |||||
| import java.io.IOException; | |||||
| import java.io.Writer; | |||||
| import java.util.Set; | |||||
| import java.util.SortedSet; | |||||
| import java.util.TreeSet; | |||||
| // 目前仅仅处理@Data,且必须在lombok自己的processor之前执行,千万注意!!!!! | |||||
| @SupportedAnnotationTypes("lombok.Data") | |||||
| @SupportedSourceVersion(SourceVersion.RELEASE_7) | |||||
| public class GraalProcessor extends AbstractProcessor { | |||||
| private static final String REFLECTION_CONFIG_JSON = "reflection-config.json"; | |||||
| private static final String NATIVE_IMAGE_PROPERTIES = "native-image.properties"; | |||||
| private SortedSet<String> classSet = new TreeSet<>(); | |||||
| private String shortestPackageName = null; | |||||
| @Override | |||||
| public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { | |||||
| for (TypeElement annotatedClass : ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Data.class))) { | |||||
| registerClass(annotatedClass.getQualifiedName().toString()); | |||||
| handleSuperClass(annotatedClass); | |||||
| } | |||||
| //只有最后一轮才可以写文件,否则文件会被重复打开,报错! | |||||
| if (!roundEnv.processingOver()) return false; | |||||
| // 如果没有文件要写,跳过 | |||||
| if (classSet.isEmpty()) return false; | |||||
| writeFiles(); | |||||
| //必须返回false,以便让lombok能继续处理。 | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * 设置当前最短的package名称 | |||||
| * | |||||
| * @param packageName 包名 | |||||
| */ | |||||
| private void setShortestPackageName(String packageName) { | |||||
| if (shortestPackageName == null) { | |||||
| shortestPackageName = packageName; | |||||
| } else if (packageName.length() < shortestPackageName.length()) { | |||||
| shortestPackageName = packageName; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 更加完整的类名来获取package名称 | |||||
| * | |||||
| * @param fullClassName 完整的类名 | |||||
| * @return package name | |||||
| */ | |||||
| private String getPackageName(String fullClassName) { | |||||
| int last = fullClassName.lastIndexOf('.'); | |||||
| if (last == -1) return fullClassName; | |||||
| return fullClassName.substring(0, last); | |||||
| } | |||||
| /** | |||||
| * 保存文件 | |||||
| * META-INF/native-image/.../reflection-config.json | |||||
| * META-INF/native-image/.../native-image.properties | |||||
| */ | |||||
| private void writeFiles() { | |||||
| String basePackage = shortestPackageName; | |||||
| String module; | |||||
| if (basePackage.contains(".")) { | |||||
| final int i = basePackage.lastIndexOf('.'); | |||||
| module = basePackage.substring(i + 1); | |||||
| basePackage = basePackage.substring(0, i); | |||||
| } else { | |||||
| module = basePackage; | |||||
| } | |||||
| String path = "META-INF/native-image/" + basePackage + "/" + module + "/"; | |||||
| String reflectFile = path + REFLECTION_CONFIG_JSON; | |||||
| String propsFile = path + NATIVE_IMAGE_PROPERTIES; | |||||
| try { | |||||
| FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", propsFile); | |||||
| Writer writer = fileObject.openWriter(); | |||||
| writer.append("Args = -H:ReflectionConfigurationResources=${.}/" + REFLECTION_CONFIG_JSON); | |||||
| writer.close(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| try { | |||||
| FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", reflectFile); | |||||
| Writer writer = fileObject.openWriter(); | |||||
| writer.write("[\n"); | |||||
| boolean first = true; | |||||
| for (String name : classSet) { | |||||
| if (first) { | |||||
| first = false; | |||||
| } else { | |||||
| writer.write(","); | |||||
| } | |||||
| writer.write(assetGraalJsonElement(name)); | |||||
| writer.append('\n'); | |||||
| } | |||||
| writer.write("]"); | |||||
| writer.close(); | |||||
| } catch (IOException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| } | |||||
| private String assetGraalJsonElement(String className) { | |||||
| return "{\n" + | |||||
| " \"name\" : \"" + className + "\",\n" + | |||||
| " \"allDeclaredFields\":true,\n" + | |||||
| " \"allDeclaredMethods\":true,\n" + | |||||
| " \"allDeclaredConstructors\":true,\n" + | |||||
| " \"allPublicMethods\" : true\n" + | |||||
| "}"; | |||||
| } | |||||
| /** | |||||
| * 登记一个class | |||||
| * | |||||
| * @param className 完整的类名 | |||||
| */ | |||||
| private void registerClass(String className) { | |||||
| classSet.add(className); | |||||
| setShortestPackageName(getPackageName(className)); | |||||
| } | |||||
| /** | |||||
| * 获取一个类型的所有的父类,并登记 | |||||
| * | |||||
| * @param typeElement 类型元素 | |||||
| */ | |||||
| private void handleSuperClass(TypeElement typeElement) { | |||||
| TypeMirror superclass = typeElement.getSuperclass(); | |||||
| if (superclass.getKind() == TypeKind.DECLARED) { | |||||
| TypeElement s = (TypeElement) ((DeclaredType) superclass).asElement(); | |||||
| String sName = s.toString(); | |||||
| // ignore java.**/javax.** | |||||
| if (sName.startsWith("java.") || sName.startsWith("javax.")) return; | |||||
| registerClass(sName); | |||||
| handleSuperClass(s); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1 @@ | |||||
| cn.binarywang.wx.graal.GraalProcessor | |||||
| @@ -1,7 +1,7 @@ | |||||
| <?xml version="1.0"?> | <?xml version="1.0"?> | ||||
| <project 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" | |||||
| xmlns="http://maven.apache.org/POM/4.0.0"> | |||||
| <project 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" | |||||
| xmlns="http://maven.apache.org/POM/4.0.0"> | |||||
| <modelVersion>4.0.0</modelVersion> | <modelVersion>4.0.0</modelVersion> | ||||
| <parent> | <parent> | ||||
| <groupId>com.github.binarywang</groupId> | <groupId>com.github.binarywang</groupId> | ||||
| @@ -134,4 +134,36 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| <profiles> | |||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <annotationProcessors> | |||||
| cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||||
| </annotationProcessors> | |||||
| <annotationProcessorPaths> | |||||
| <path> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <version>${project.version}</version> | |||||
| </path> | |||||
| </annotationProcessorPaths> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </profile> | |||||
| </profiles> | |||||
| </project> | </project> | ||||
| @@ -95,4 +95,36 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| <profiles> | |||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <annotationProcessors> | |||||
| cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||||
| </annotationProcessors> | |||||
| <annotationProcessorPaths> | |||||
| <path> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <version>${project.version}</version> | |||||
| </path> | |||||
| </annotationProcessorPaths> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </profile> | |||||
| </profiles> | |||||
| </project> | </project> | ||||
| @@ -80,12 +80,12 @@ | |||||
| <groupId>org.projectlombok</groupId> | <groupId>org.projectlombok</groupId> | ||||
| <artifactId>lombok</artifactId> | <artifactId>lombok</artifactId> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>com.github.jedis-lock</groupId> | |||||
| <artifactId>jedis-lock</artifactId> | |||||
| <version>1.0.0</version> | |||||
| <optional>true</optional> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>com.github.jedis-lock</groupId> | |||||
| <artifactId>jedis-lock</artifactId> | |||||
| <version>1.0.0</version> | |||||
| <optional>true</optional> | |||||
| </dependency> | |||||
| </dependencies> | </dependencies> | ||||
| <build> | <build> | ||||
| @@ -102,4 +102,35 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| <profiles> | |||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <annotationProcessors> | |||||
| cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||||
| </annotationProcessors> | |||||
| <annotationProcessorPaths> | |||||
| <path> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <version>${project.version}</version> | |||||
| </path> | |||||
| </annotationProcessorPaths> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </profile> | |||||
| </profiles> | |||||
| </project> | </project> | ||||
| @@ -96,4 +96,35 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| <profiles> | |||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <annotationProcessors> | |||||
| cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||||
| </annotationProcessors> | |||||
| <annotationProcessorPaths> | |||||
| <path> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <version>${project.version}</version> | |||||
| </path> | |||||
| </annotationProcessorPaths> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </profile> | |||||
| </profiles> | |||||
| </project> | </project> | ||||
| @@ -107,5 +107,35 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| <profiles> | |||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <annotationProcessors> | |||||
| cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||||
| </annotationProcessors> | |||||
| <annotationProcessorPaths> | |||||
| <path> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <version>${project.version}</version> | |||||
| </path> | |||||
| </annotationProcessorPaths> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </profile> | |||||
| </profiles> | |||||
| </project> | </project> | ||||
| @@ -72,4 +72,35 @@ | |||||
| </dependency> | </dependency> | ||||
| </dependencies> | </dependencies> | ||||
| <profiles> | |||||
| <profile> | |||||
| <id>native-image</id> | |||||
| <activation> | |||||
| <activeByDefault>false</activeByDefault> | |||||
| </activation> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.apache.maven.plugins</groupId> | |||||
| <artifactId>maven-compiler-plugin</artifactId> | |||||
| <version>3.5.1</version> | |||||
| <configuration> | |||||
| <annotationProcessors> | |||||
| cn.binarywang.wx.graal.GraalProcessor,lombok.launch.AnnotationProcessorHider$AnnotationProcessor,lombok.launch.AnnotationProcessorHider$ClaimingProcessor | |||||
| </annotationProcessors> | |||||
| <annotationProcessorPaths> | |||||
| <path> | |||||
| <groupId>com.github.binarywang</groupId> | |||||
| <artifactId>weixin-graal</artifactId> | |||||
| <version>${project.version}</version> | |||||
| </path> | |||||
| </annotationProcessorPaths> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </profile> | |||||
| </profiles> | |||||
| </project> | </project> | ||||