首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

Java 动态编译工具 Janino 和 Liquor 差别

编程知识
2024年09月24日 08:38

如果你只要 Java7 及以下的语法支持,建议 Janino。如果要你想更全的 Java8、Java11、Java17、Java21 等语法,可以选 Liquor。

1、它们相同的地方

  • 提供的相似的能力接口
接口 Janino Liquor
动态编译器 SimpleCompiler DynamicCompiler
表达式评估器 ExpressionEvaluator LiquorEvaluator (Exprs)
脚本评估器 ScriptEvaluator LiquorEvaluator (Scripts)
  • 都是 Java 语言(语法)的动态应用。生成的字节码都可以完全访问 JRE,可能要注意安全的控制。

2、细节区别处

  • Janino 基于自已的编译能力实现。
    • 支持 Java7 及以下语法。
    • 单次编译性能,更好。
    • 支持命令行编译。
    • 提供更丰富的功能。比如代码分析器,等。
  • Liquor 基于 JDK 自带的编译能力实现。
    • 支持 Java8、Java11、Java17、Java21 等语法(由运行时版本决定)。
    • 单次编译性能,差些。
    • 不支持命令行编译。可用 javac 命令。

3、具体差异 - 动态编译器

动态编译器的性能,基本上可以按“次”计量。次数越多,费时越多。尽量把可知代码,合在一起编译(次数,越少越好)。

  • Janino
public class JaninoTest {
    public static void main(String[] args) throws Exception {
        //此类,不可以复用(可以通过别的方式,实现多类一起编译)
        SimpleCompiler compiler = new SimpleCompiler();
        
        String className = "HelloWorld";
        String classCode = "public class HelloWorld { " +
                "   public static void helloWorld() { " +
                "       System.out.println(\"Hello, world!\"); " +
                "   } " +
                "}";
        
        //只能单个编译
        compiler.cook(classCode);
        
        //再 cook ,则会异常

        Class<?> clazz = compiler.getClassLoader().loadClass(className);
        clazz.getMethod("helloWorld").invoke(null);
    }
}
  • Liquor
public class LiquorTest {
    public static void main(String[] args) throws Exception{
        //可以复用(可以,不断的增量编译)
        DynamicCompiler compiler = new DynamicCompiler();
        
        String className = "HelloWorld";
        String classCode = "public class HelloWorld { " +
                "   public static void helloWorld() { " +
                "       System.out.println(\"Hello, world!\"); " +
                "   } " +
                "}";
        
        //可添加多个源码
        compiler.addSource(className, classCode);
        compiler.build();
        
        //构建后,仍可添加不同类的源码再构建

        Class<?> clazz = compiler.getClassLoader().loadClass(className);
        clazz.getMethod("helloWorld").invoke(null);
    }
}

4、具体差异 - 表达式评估器

比较 Janino Liquor
缓存 无(可以自己包装) 有二级缓存(类加载器缓存,编译结果缓存)
体验 每次要重新构建 方便
性能 单次更好 缓存命名时,非常好(接近原始 Java 代码性能)
  • Janino
public class JaninoTest {
    public static void main(String[] args) throws Exception {
        //每次要新实例化
        ExpressionEvaluator ee = new ExpressionEvaluator(); 
        ee.cook("3 + 4"); 
        System.out.println(ee.evaluate()); 
    }
}
  • Liquor
public class LiquorTest {
    public static void main(String[] args) throws Exception {
        //单例,可复用,线程安全
        System.out.println(Exprs.eval("3 + 4"));
    }
}

5、具体差异 - 脚本评估器

比较 Janino Liquor
缓存 无(可以自己包装) 有二级缓存(类加载器缓存,编译结果缓存)
体验 每次要重新构建 方便
性能 单次更好 缓存命名时,非常好(接近原始 Java 代码性能)
  • Janino
public class JaninoTest {
    public static void main(String[] args) throws Exception {
        //每次要新实例化
        ScriptEvaluator se = new ScriptEvaluator(); 
        se.cook("System.out.println(\"hello word\");"); 
        se.evaluate();
    }
}
  • Liquor
public class LiquorTest {
    public static void main(String[] args) throws Exception {
        //单例,可复用,线程安全
        Scripts.eval("System.out.println(\"hello word\");");
    }
}
From:https://www.cnblogs.com/noear/p/18428398
本文地址: http://www.shuzixingkong.net/article/2256
0评论
提交 加载更多评论
其他文章 让人眼前一亮的开源项目「GitHub 热点速览」
时隔两周,我又带着让人眼前一亮的开源项目回来了! 告别数据线、蓝牙、WiFi 和网络,只需用手机的摄像头扫描一张动图条形码(需安装应用),就能在设备间传输文件的 libcimbar,一款无需联网和蓝牙的文件传输工具,仅用摄像头传输数据。用 Rust 编写的 PostgreSQL 数据库命令行管理工具
让人眼前一亮的开源项目「GitHub 热点速览」 让人眼前一亮的开源项目「GitHub 热点速览」 让人眼前一亮的开源项目「GitHub 热点速览」
React的useId,现在Vue3.5终于也有了!
前言 React在很早之前的版本中加了useId,用于生成唯一ID。在Vue3.5版本中,终于也有了期待已久的useId。这篇文章来带你搞清楚useId有哪些应用场景,以及他是如何实现的。 关注公众号:【前端欧阳】,给自己一个进阶vue的机会 useId的作用 他的作用也是生成唯一ID,同一个Vue
React的useId,现在Vue3.5终于也有了! React的useId,现在Vue3.5终于也有了! React的useId,现在Vue3.5终于也有了!
Java——图片文件位于 bin 目录下,下载新图片会导致应用程序重启
当应用程序在运行时需要加载图片文件时,如果图片文件位于 bin 目录下,下载新图片会导致应用程序重启,这是因为 Java 应用程序在加载资源时通常会遵循以下机制: 类加载器: Java 应用程序使用类加载器来加载类文件和资源。 资源加载: 类加载器会根据类路径(classpath)来查找资源,而 b
统计一个字符在字符串里出现的次数
统计一个字符在字符串里出现的次数 背景在数据库操作中,统计字符串中某个特定字符出现的次数是一个常见需求。无论是分析文本数据、格式化字符串,还是确保数据一致性,字符出现次数的统计对于开发人员和数据库管理员来说都是一项重要任务。这个问题看似简单,但可以通过数据库管理系统的内置函数高效解决,避免复杂的循环
统计一个字符在字符串里出现的次数
MoNA:复用跨模态预训练模型,少样本模态的福音 | ICML'24
跨模态转移旨在利用大型预训练模型来完成可能不属于预训练数据模态的任务。现有的研究在将经典微调扩展到跨模态场景方面取得了一定的成功,但仍然缺乏对模态差距对转移的影响的理解。在这项工作中,进行了一系列关于转移过程中源表示质量的实验,揭示了更大的模态差距与较少知识重用之间的联系,这意味着转移效果不佳。然后
MoNA:复用跨模态预训练模型,少样本模态的福音 | ICML'24 MoNA:复用跨模态预训练模型,少样本模态的福音 | ICML'24 MoNA:复用跨模态预训练模型,少样本模态的福音 | ICML'24
redisson内存泄漏问题排查
问题描述 最近生产有个服务突然出现频繁告警,接口P99响应时间变长,运维同学观察到相应的pod cpu飙升,内存占用很高。 cpu升高问题排查是老生常谈的话题了,一般可以使用top -p pid -H查看是哪个线程占用cpu高,再结合jstack找到对应的java线程代码。 不过经验告诉我们,cpu
redisson内存泄漏问题排查 redisson内存泄漏问题排查 redisson内存泄漏问题排查
.NET 8 + Vue/UniApp 高性能前后端分离框架
前言 作为一名开发者,我们知道能够简化开发流程、提升工作效率的工具是至关重要的。 推荐一款前后端分离框架 Admin.NET(ZRAdmin),它不仅可以满足项目开发的需求,还应用了一些新的特性,如RBAC权限管理、SqlSugar ORM、以及Vue3的动态国际化支持,代码简洁易用。 接下来,让我
.NET 8 + Vue/UniApp 高性能前后端分离框架 .NET 8 + Vue/UniApp 高性能前后端分离框架 .NET 8 + Vue/UniApp 高性能前后端分离框架
除了递归算法,要如何优化实现文件搜索功能
大家好,我是 V 哥,今天的文章来聊一聊 Java实现文件搜索功能,并且比较递归算法、迭代方式和Memoization技术的优缺点。 以下是一个使用 Java 实现的文件搜索功能,它会在指定目录及其子目录中搜索包含特定关键字的文件。此实现使用递归方式遍历目录,并可以使用文件名或内容搜索文件。 使用递