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参数。具体代码如下:
-
Map<String, byte[]> compileFromJava(@NotNull String className, @NotNull String javaCode, @NotNull final PrintWriter writer, MyJavaFileManager fileManager) {
-
Object compilationUnits;
-
if(this.sourceDir != null) {
-
String filename = className.replaceAll("\\.", '\\' + File.separator) + ".java";
-
File file = new File(this.sourceDir, filename);
-
CompilerUtils.writeText(file, javaCode);
-
compilationUnits = CompilerUtils.s_standardJavaFileManager.getJavaFileObjects(new File[]{file});
-
} else {
-
this.javaFileObjects.put(className, new JavaSourceFromString(className, javaCode));
-
compilationUnits = this.javaFileObjects.values();
-
}
-
System.setProperty("useJavaUtilZip", "true");
-
List<String> options = new ArrayList<>();
-
options.add("-encoding");
-
options.add("UTF-8");
-
options.add("-classpath");
-
//获取系统构建路径
-
options.add(buildClassPath());
-
//不使用SharedNameTable (jdk1.7自带的软引用,会影响GC的回收,jdk1.9已经解决)
-
options.add("-XDuseUnsharedTable");
-
options.add("-XDuseJavaUtilZip");
-
-
boolean ok = CompilerUtils.s_compiler.getTask(writer, fileManager, new DiagnosticListener<JavaFileObject>() {
-
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
-
if(diagnostic.getKind() == Kind.ERROR) {
-
writer.println(diagnostic);
-
}
-
-
}
-
}, options, (Iterable)null, (Iterable)compilationUnits).call().booleanValue();
-
Map<String, byte[]> result = fileManager.getAllBuffers();
-
if(!ok) {
-
if(this.sourceDir == null) {
-
this.javaFileObjects.remove(className);
-
}
-
-
return Collections.emptyMap();
-
} else {
-
return result;
-
}
-
}
3、具体编译时测试类
利用原来的测试类,以10万个编译测试为例,进行测试,编译速度提升N倍,同时内存溢出问题也仅存在ZipFIleIndex
-
package com.yunerp.web.util.run.compile;
-
-
import com.yunerp.web.util.run.WebInterface;
-
import com.yunerp.web.util.run.dynamic.compiler.CompilerUtils;
-
-
import java.util.HashMap;
-
import java.util.Map;
-
-
public class DynaCompTest{
-
-
public static Map<String,Object> map = new HashMap<>();
-
-
-
public static void main(String[] args) throws Exception {
-
-
String code = "import java.util.HashMap;\n" +
-
"import com.yunerp.web.vaadin.message.alert;\n" +
-
"import java.util.List;\n" +
-
"import java.util.ArrayList;\n" +
-
"import com.yunerp.web.vaadin.util.modularfuntion.base.BaseUtil;\n" +
-
"import com.yunerp.web.vaadin.util.function.TableFuntionUtil;\n" +
-
"import com.yunerp.web.vaadin.util.modularfuntion.stoUtil.StoUtil;\n" +
-
"import java.util.Map;import com.yunerp.web.vaadin.util.modularfuntion.user.mini.HomePageUtil;\n" +
-
"import com.yunerp.web.util.run.WebInterface;\n" +
-
"\n" +
-
"public class web2905763164651825363 implements WebInterface {\n" +
-
" public Object execute(Map<String,Object> param) {\n" +
-
" System.out.println(param.get(\"key\")+ \"次测试编译\");" +
-
" return null;\n" +
-
" }\n" +
-
"}";
-
String name = "web2905763164651825363";
-
-
for(int i=0;i<100000;i++){
-
long time1 = System.currentTimeMillis();
-
DynamicEngine de = new DynamicEngine();
-
try {
-
// Class cl = de.javaCodeToObject(name,code);
-
Class cl = CompilerUtils.CACHED_COMPILER.loadFromJava(name, code);
-
if (cl==null){
-
-
System.out.println("编译失败/类加载失败");
-
continue;
-
}
-
WebInterface webInterface = (WebInterface)cl.newInstance();
-
Map<String,Object> param = new HashMap<>();
-
param.put("key",i);
-
webInterface.execute(param);
-
}catch (Exception e) {
-
e.printStackTrace();
-
}
-
long time2 = System.currentTimeMillis();
-
System.out.println("次数:"+i+" time:"+(time2-time1));
-
}
-
-
}
-
-
}
4、编译速度对比
之前的编译代码编译速度:
使用更改后的第三方编译代码编译速度如下:
注: 因为之前的就存在ZipFileIndex问题,更改后的编译源码也只是提升编译速度,ZipFileIndex内存泄漏的问题仍然存在,目前唯一的解决方案是升级Java8 到 Java10
原文地址:https://blog.csdn.net/moneyshi/article/details/82499058
Java动态编译优化——提升编译速度(N倍)的更多相关文章
- COCOS2DX 3.0 优化提升渲染速度 Auto-batching
COCOS2DX 3.0 优化提升渲染速度 Auto-batching 近期在看COCOS2DX 3.0的Auto-batching合批与Auto Culling动态缩减功能以下就来细致看看吧:整合好 ...
- vue-cli3使用 DllPlugin 实现预编译,提升构建速度
在项目打包上有两个目标:减少打包代码体积和加快打包速度 1. 减少打包体积: (1)对于用的比较少的库,可以去掉(我去掉了jquery以及lodash),用到的地方,参考源码自己写 (2)非用不可的又 ...
- java 动态生成类再编译最后代理
package spring.vhostall.com.proxy; public interface Store { public void sell(); } ------------------ ...
- js优化提升访问速度
一.给JS文件减肥. 有的人为了给网站增加炫目效果,往往会使用一些JS效果代码,这在上个世纪似乎还很流行,对于现在来说,最好在用户体验确实需要的情况下,使用这些东西.至于希望给自己的JS文件减肥的童鞋 ...
- JVM性能优化系列-(6) 晚期编译优化
6. 晚期编译优化 晚期编译优化主要是在运行时做的一些优化手段. 6.1 JIT编译器 在部分的商用虚拟机中,java程序最初是通过解释器(Interpreter) 进行解释执行的,当虚拟机发现某个方 ...
- JVM性能优化系列-(5) 早期编译优化
5. 早期编译优化 早起编译优化主要指编译期进行的优化. java的编译期可能指的以下三种: 前端编译器:将.java文件变成.class文件,例如Sun的Javac.Eclipse JDT中的增量式 ...
- Java程序性能优化Tip
本博客是阅读<java time and space performance tips>这本小书后整理的读书笔记性质博客,增加了几个测试代码,代码可以在此下载:java时空间性能优化测试代 ...
- 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结
1.引言 岁月真是个养猪场,这几年,人胖了,微信代码也翻了. 记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟.如今用公司配的 17 年款 27-inch iMac 编译要接近半小时:偶 ...
- JavaScript的工作原理:解析、抽象语法树(AST)+ 提升编译速度5个技巧
这是专门探索 JavaScript 及其所构建的组件的系列文章的第 14 篇. 如果你错过了前面的章节,可以在这里找到它们: JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述! Jav ...
随机推荐
- RocksDB 之Write Ahead Log(WAL)
Overview RocksDB 中有三个基本的数据结构概念:memtable, sstfile 和 logfile memtable 是个内存数据结构,新写入会插入memtable 切回选择性地写入 ...
- iOS开发 底层抛析运行循环—— RunLoop
http://blog.csdn.net/zc639143029/article/details/50012527 一.RunLoop基本概念 概念:程序的运行循环,通俗的来说就是跑圈. 1. 基本作 ...
- 洛谷 P3951 小凯的疑惑 找规律
目录 题面 题目链接 题目描述 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例: 输出样例: 说明 思路 证明 AC代码 include<bits/stdc++.h> 题面 ...
- Vagrant-安装教程及常见问题
http://ju.outofmemory.cn/entry/346215 前言: Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境. 它的主要意义是让所有开发人员都使用和线上服务 ...
- Otracle数据库定时任务--dbms_job
一.dbms_job涉及到的知识点 1.创建job: variable jobno number; dbms_job.submit(:jobno, --job号 'your_procedure;'-- ...
- POJ 2632 Crashing Robots (模拟 坐标调整)(fflush导致RE)
题目链接:http://poj.org/problem?id=2632 先话说昨天顺利1Y之后,直到今天下午才再出题 TAT,真是刷题计划深似海,从此AC是路人- - 本来2632是道略微恶心点的模拟 ...
- 并发编程之submit和execute区别
前言 使用线程池难免会用到submit和execute,但是submit是有坑的,此处做个记录 1.submit坑 此处随便写一个方法,进入内部查看execute和submit /** * @Auth ...
- iOS 警告收录及科学快速的消除方法
http://www.cocoachina.com/ios/20150914/13287.html 作者:董铂然 授权本站转载. 前言:现在你维护的项目有多少警告?看着几百条警告觉得心里烦么?你真的觉 ...
- 归并排序及应用 (nyoj 117 求逆序数)
求逆序数 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中 ...
- C# Find vs FirstOrDefault
本文告诉大家,在获得数组第一个元素时,使用哪个方法性能更高. 需要知道,两个方法都是 Linq 的方法,使用之前需要引用 Linq .对于 List 等都是继承可枚举Enumerable这时获取第一个 ...