zoukankan      html  css  js  c++  java
  • Java动态编译优化——提升编译速度(N倍)

    一、前言

    最近一直在研究Java8 的动态编译, 并且也被ZipFileIndex$Entry 内存泄漏所困扰,在无意中,看到一个第三方插件的动态编译。并且编译速度是原来的2-3倍。原本打算直接用这个插件,但是发现插件的编译源码存在我之前已经解决过的内存泄漏问题。所以拿其源码,进行改善。

    二、第三方插件

    1、maven配置

    我找到的这个第三方编译插件有两个,第一个是:Talismane Utilities ,在maven仓库中可搜到相关pom的配置:

    http://mvnrepository.com/search?q=Talismane+Utilities

    这个插件也能编译,但是编译速度和内存泄漏问题依然存在(废弃)

    第二个插件是Java Runtime Compiler , 可在Maven仓库中找到 :   http://mvnrepository.com/artifact/net.openhft/compiler

    我使用的版本是最新的2.3.1 ,  进行反编译后:

    2、插件源码更改

    拿到Java Runtime Compiler插件的源码后,能找到有个CachedCompiler类,我对其compilerFromJava方法进行了更改,加上了编译options参数。具体代码如下:

    1. Map<String, byte[]> compileFromJava(@NotNull String className, @NotNull String javaCode, @NotNull final PrintWriter writer, MyJavaFileManager fileManager) {
    2. Object compilationUnits;
    3. if(this.sourceDir != null) {
    4. String filename = className.replaceAll("\.", '\' + File.separator) + ".java";
    5. File file = new File(this.sourceDir, filename);
    6. CompilerUtils.writeText(file, javaCode);
    7. compilationUnits = CompilerUtils.s_standardJavaFileManager.getJavaFileObjects(new File[]{file});
    8. } else {
    9. this.javaFileObjects.put(className, new JavaSourceFromString(className, javaCode));
    10. compilationUnits = this.javaFileObjects.values();
    11. }
    12. System.setProperty("useJavaUtilZip", "true");
    13. List<String> options = new ArrayList<>();
    14. options.add("-encoding");
    15. options.add("UTF-8");
    16. options.add("-classpath");
    17. //获取系统构建路径
    18. options.add(buildClassPath());
    19. //不使用SharedNameTable (jdk1.7自带的软引用,会影响GC的回收,jdk1.9已经解决)
    20. options.add("-XDuseUnsharedTable");
    21. options.add("-XDuseJavaUtilZip");
    22. boolean ok = CompilerUtils.s_compiler.getTask(writer, fileManager, new DiagnosticListener<JavaFileObject>() {
    23. public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
    24. if(diagnostic.getKind() == Kind.ERROR) {
    25. writer.println(diagnostic);
    26. }
    27. }
    28. }, options, (Iterable)null, (Iterable)compilationUnits).call().booleanValue();
    29. Map<String, byte[]> result = fileManager.getAllBuffers();
    30. if(!ok) {
    31. if(this.sourceDir == null) {
    32. this.javaFileObjects.remove(className);
    33. }
    34. return Collections.emptyMap();
    35. } else {
    36. return result;
    37. }
    38. }

    3、具体编译时测试类

    利用原来的测试类,以10万个编译测试为例,进行测试,编译速度提升N倍,同时内存溢出问题也仅存在ZipFIleIndex

    1. package com.yunerp.web.util.run.compile;
    2. import com.yunerp.web.util.run.WebInterface;
    3. import com.yunerp.web.util.run.dynamic.compiler.CompilerUtils;
    4. import java.util.HashMap;
    5. import java.util.Map;
    6. public class DynaCompTest{
    7. public static Map<String,Object> map = new HashMap<>();
    8. public static void main(String[] args) throws Exception {
    9. String code = "import java.util.HashMap; " +
    10. "import com.yunerp.web.vaadin.message.alert; " +
    11. "import java.util.List; " +
    12. "import java.util.ArrayList; " +
    13. "import com.yunerp.web.vaadin.util.modularfuntion.base.BaseUtil; " +
    14. "import com.yunerp.web.vaadin.util.function.TableFuntionUtil; " +
    15. "import com.yunerp.web.vaadin.util.modularfuntion.stoUtil.StoUtil; " +
    16. "import java.util.Map;import com.yunerp.web.vaadin.util.modularfuntion.user.mini.HomePageUtil; " +
    17. "import com.yunerp.web.util.run.WebInterface; " +
    18. " " +
    19. "public class web2905763164651825363 implements WebInterface { " +
    20. " public Object execute(Map<String,Object> param) { " +
    21. " System.out.println(param.get("key")+ "次测试编译");" +
    22. " return null; " +
    23. " } " +
    24. "}";
    25. String name = "web2905763164651825363";
    26. for(int i=0;i<100000;i++){
    27. long time1 = System.currentTimeMillis();
    28. DynamicEngine de = new DynamicEngine();
    29. try {
    30. // Class cl = de.javaCodeToObject(name,code);
    31. Class cl = CompilerUtils.CACHED_COMPILER.loadFromJava(name, code);
    32. if (cl==null){
    33. System.out.println("编译失败/类加载失败");
    34. continue;
    35. }
    36. WebInterface webInterface = (WebInterface)cl.newInstance();
    37. Map<String,Object> param = new HashMap<>();
    38. param.put("key",i);
    39. webInterface.execute(param);
    40. }catch (Exception e) {
    41. e.printStackTrace();
    42. }
    43. long time2 = System.currentTimeMillis();
    44. System.out.println("次数:"+i+" time:"+(time2-time1));
    45. }
    46. }
    47. }

    4、编译速度对比

    之前的编译代码编译速度:

    使用更改后的第三方编译代码编译速度如下:

    注: 因为之前的就存在ZipFileIndex问题,更改后的编译源码也只是提升编译速度,ZipFileIndex内存泄漏的问题仍然存在,目前唯一的解决方案是升级Java8 到 Java10

    原文地址:https://blog.csdn.net/moneyshi/article/details/82499058
  • 相关阅读:
    poj 1088 滑雪
    位运算与bitset
    hdu 4607 Park Visit
    树的直径
    codeforces 495D Sonya and Matrix
    German Collegiate Programming Contest 2015(第三场)
    BAPC 2014 Preliminary(第一场)
    Benelux Algorithm Programming Contest 2014 Final(第二场)
    E. Reachability from the Capital(tarjan+dfs)
    poj2104 K-th Number(划分树)
  • 原文地址:https://www.cnblogs.com/jpfss/p/10978351.html
Copyright © 2011-2022 走看看