动态编译依赖于特定类加载器加载的类的java代码

2024-01-20

我们有能力即时动态编译 Java 代码。 我至少知道Java 运行时编译器 https://github.com/OpenHFT/Java-Runtime-Compiler and 内存Java编译器 https://github.com/trung/InMemoryJavaCompiler

但似乎他们无法编译依赖于某些类加载器中的某些类的类。

是否可以动态编译依赖于仅在特定类加载器中可用的类的java代码?比方说:

ClassLoader classloader = ... // only this CL can load class 'com.External'
String source = "public class MyClass extends com.External {}";
Class<?> compiled = DesiredDynamicCompiler.compile("MyClass", source, classloader); 
// last argument is like an information to compiler where to search all dependencies

为了提供更多见解:我想在 java 中执行 GroovyClassLoader 在 groovy 中可以执行的操作:

GroovyClassLoader groovyClassLoader = new GroovyClassLoader(classLoader);
Class<?> parsedClass = groovyClassLoader.parseClass("some source");

该代码可以解析依赖于仅在指定类加载器中可用的类的类。


没有办法使用ClassLoader作为参考,除非它能够提供其定义类的类字节。也就是说,如果你有一个Class代表顶级类的实例,您可以使用classInstance.getResourceAsStream(classInstance.getSimpleName()+".class")尝试获取类字节。如果您有权访问构成动态类的字节,则可以通过 java 编译器将它们提供给JavaFileManager https://docs.oracle.com/javase/8/docs/api/?javax/tools/JavaFileManager.html执行。

编译器 API 是标准 API 的一部分,不需要第三方库。以下代码通过首先编译测试类,然后根据上一步中刚刚创建的类设置必要的环境来编译第二个类来演示这一点:

// customize these, if you want, null triggers default behavior
DiagnosticListener<JavaFileObject> diagnosticListener = null;
Locale locale = null;

// the first class, to be present at runtime only
String class1 = "package test;\npublic class Class1 {}";
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm
    = c.getStandardFileManager(diagnosticListener, locale, Charset.defaultCharset());
// define where to store compiled class files - use a temporary directory
fm.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(
        Files.createTempDirectory("compile-test").toFile()));
JavaCompiler.CompilationTask task = c.getTask(null, fm,
    diagnosticListener, Collections.emptySet(), Collections.emptySet(),
    Collections.singleton(new SimpleJavaFileObject(
        URI.create("string:///Class1.java"), Kind.SOURCE) {
            public CharSequence getCharContent(boolean ignoreEncodingErrors) {
                return class1;
            }
        }));
if(task.call()) {
    FileObject fo = fm.getJavaFileForInput(
            StandardLocation.CLASS_OUTPUT, "test.Class1", Kind.CLASS);
    // these are the class bytes of the first class
    byte[] class1bytes = Files.readAllBytes(Paths.get(fo.toUri()));

    // the actual task: define a class dependent on the first class
    String class2 = "package test;\npublic class Class2 { Class1 variable; }";

    // create a file object representing the dynamic class
    JavaFileObject jo = new SimpleJavaFileObject(
        URI.create("runtime:///test/Class1.class"), Kind.CLASS) {
            @Override public InputStream openInputStream() throws IOException {
                return new ByteArrayInputStream(class1bytes);
            }
        };

    // and a custom file manager knowing how to locate that class
    JavaFileManager myFM = new ForwardingJavaFileManager(fm) {
        @Override
        public JavaFileObject getJavaFileForInput(
                JavaFileManager.Location location, String className, Kind kind)
                throws IOException {
            if(location==StandardLocation.CLASS_PATH&&className.equals("test.Class1")) {
                return jo;
            }
            return super.getJavaFileForInput(location, className, kind);
        }

        @Override
        public boolean hasLocation(JavaFileManager.Location location) {
            return location==StandardLocation.CLASS_PATH || super.hasLocation(location);
        }

        @Override
        public Iterable list(JavaFileManager.Location location,
                String packageName, Set kinds, boolean recurse) throws IOException {
            if(location==StandardLocation.CLASS_PATH
                    && (packageName.equals("test") || recurse&&packageName.isEmpty())) {
                return Collections.singleton(jo);
            }
            return super.list(location, packageName, kinds, recurse);
        }

        @Override
        public String inferBinaryName(
                JavaFileManager.Location location, JavaFileObject file) {
            if(file==jo) return "test.Class1";
            return super.inferBinaryName(location, file);
        }
    };
    // compile the second class using the custom file manager to locate dependencies
    task = c.getTask(null, myFM,
        diagnosticListener, Collections.emptySet(), Collections.emptySet(),
        Collections.singleton(new SimpleJavaFileObject(
            URI.create("string:///Class2.java"), Kind.SOURCE) {
                public CharSequence getCharContent(boolean ignoreEncodingErrors) {
                    return class2;
                }
            }));
    if(task.call()) {
        fo = fm.getJavaFileForInput(
            StandardLocation.CLASS_OUTPUT, "test.Class2", Kind.CLASS);
        // there we have the compiled second class
        byte[] class2bytes = Files.readAllBytes(Paths.get(fo.toUri()));
    }
}

当然,这只是为了演示原理。您肯定想为文件对象创建工厂方法并使用Maps 用于记住它们等等。

还可以用自定义内存存储替换临时目录。但关键点仍然是,编译器需要能够访问类字节。它不会使用加载的运行时类。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态编译依赖于特定类加载器加载的类的java代码 的相关文章

  • Spring与AspectJ编译时编织导致:java.lang.VerifyError:非法使用非虚拟函数调用

    我正在尝试使用 Spring 的 AspectJ 编译时编织而不是
  • 在 Java 中将系统属性设置为 Null

    在我的单元测试中 我需要将 workingDir 系统属性设置为 Null 但我不能这样做 因为它给了我 NullPointerException System setProperty workingDir null 我该怎么做 您不能将属
  • java.lang.unsatisfiedlinkerror 无法加载 amd 64 位 .dll ia 32 位

    当我尝试在 Eclipse 上运行我的项目时 出现以下错误 它在我开发它的计算机上运行良好 但当我将其导入我的笔记本电脑时 它不起作用 这个问题已经在本网站的其他地方提出过 这个问题的主要原因似乎是环境变量设置不正确 但我检查过 它们似乎是
  • 如何在 Spring Boot 1.4 中自定义 Jackson

    我一直无法找到如何使用的示例Jackson2ObjectMapperBuilderCustomizer java在spring boot 1 4中自定义Jackson的功能 boot 1 4 中自定义 Jackson 的 doco http
  • 将对象列表传递给 Freemarker 然后循环

    我已经熟悉了 FreeMarker 一个 Java 模板引擎 我已经能够通过哈希映射将对象传递给模板引擎了 这样就可以了 但是 一旦我尝试将任何类型的多个对象集传递给 FreeMarker 它就会给我一个 freemarker templa
  • 使用java在mysql中插入带有\\的文件路径

    我正在使用java制作一个独立的应用程序 并且我需要插入用户从文件选择器中选择的图像的路径 我正在获取文件的路径 但是当我将其存储在数据库 mysql 中时 它不会存储 所以当我检索该路径时 该文件不会显示 如何存储文件的路径 这样就可以使
  • 在 GORM 中重命名复合外键

    我有以下课程 class Catalog static mapping id composite name manufacturer columns name column cat name manufacturer column manu
  • 如何将用户输入密码与凭据密码进行比较

    我有一个脚本化管道 它使用以下命令请求用户的密码input函数并将其与用户保存的凭据密码进行比较 如果用户输入的是一个类型string然后就可以了 但是 当我将输入类型更改为password 因此当用户键入它时 它在屏幕上不可见 它会失败并
  • 用dagger 2查看依赖注入

    我有一个自定义视图扩展TextView 我应该在哪里调用我的组件来注入视图 component inject customTextView 因此 我发现我需要在自定义视图的构造函数中添加注入 在所有视图中 或者使一个调用另一个 Exampl
  • 如何更改tomcat jmx密码的文件权限

    我正在尝试保护 Windows 平台上托管的本地 tomcat 实例上的 JMX 访问 我已经创建了访问权限和密码文件 并使用以下 VM 参数插入这些文件 Dcom sun management jmxremote password fil
  • 使用 java.nio.file.Paths 接口时缺少方案(IllegalArgumentException)

    这是一个非常简单的java问题 我在 Linux 系统上使用 Java 8 和 eclipse kepler 我一直在尝试尝试NIO 2 我的代码是 package lucasTest import java io IOException
  • 如何告诉 Java SAX 解析器忽略无效字符引用?

    当尝试使用字符引用解析不正确的 XML 时 例如 x1 Java 的 SAX 解析器因致命错误而惨死 例如 org xml sax SAXParseException Character reference x1 is an invalid
  • 将 Class 对象转换为字节

    如果我有一个Class http java sun com j2se 1 5 0 docs api java lang Class html在运行时实例 我可以获得它的 byte 表示形式吗 我感兴趣的字节将在类文件格式 http java
  • Java 通用问题

    下面的代码可以编译 但如果我取消注释行 它不会编译 我很困惑为什么 HashMap 确实扩展了 AbstractMap 并且声明映射的第一行可以正常编译 import java util AbstractMap import java ut
  • Hive NVL 不适用于列的日期类型 - NullpointerException

    我正在使用 HDFS 上的 MapR Hive 发行版并面临以下问题 如果表的列类型是 日期 类型 则NVL https cwiki apache org confluence display Hive LanguageManual UDF
  • bean 中的 Spring JavaConfig 属性未设置?

    我正在考虑将 Spring JavaConfig 与一些属性文件一起使用 但 bean 中的属性未设置 bean 中的属性未设置 这是我的网络配置 Configuration EnableWebMvc PropertySource valu
  • 在 Java Web 应用程序中获取 DataSource 资源

    我的 context xml 文件中有以下资源标记
  • 使用 JPA 和 Hibernate 时 DISTINCT 如何工作

    DISTINCT 在 JPA 中使用什么列 是否可以更改它 以下是使用 DISTINCT 的 JPA 查询示例 select DISTINCT c from Customer c 这没有多大意义 不同的列是基于哪一列 它是否在实体上指定为注
  • Selenium Webdriver 中的 IF 语句

    我想知道是否有人可以帮助我解决我正在尝试解决的问题以及 Java 中 Webdriver 的 If 语句 当登录到我正在测试的应用程序时 可以在主页之前进入安全问题页面 如果是新用户等 我希望测试中的代码做的是 如果出现安全问题页面 请填写
  • Ant 类路径和 junit.jar

    我有一个 build xml 它允许我运行 junit 测试 这是相关部分

随机推荐

  • 如何在 php 中添加 txt 文件并创建 ZIP [重复]

    这个问题在这里已经有答案了 可能的重复 打开文件 写入文件 将文件另存为 zip 并流式传输给用户下载 https stackoverflow com questions 2286639 open file write to file sa
  • Xcode 7 GM 无法验证 git 存储库

    我可以使用 Xcode 6 毫无问题地提交到这个存储库 git 在终端中仍然可以正常工作 我可以在本地和远程提交 在 Xcode 7 中 我可以本地提交 但不能远程提交 它说身份验证失败并且无法重置用户名 它呈灰色 我的本地 git 配置文
  • Vue router - 如何根据用户角色在同一路由路径上加载多个组件?

    我有一个应用程序 用户可以以不同的角色登录 例如 seller buyer and admin 对于每个用户 我想在同一路径上显示仪表板页面 例如 http localhost 8080 dashboard然而 每个用户将在不同的 vue
  • 如何向画布元素添加简单的 onClick 事件处理程序?

    我是一名经验丰富的 Java 程序员 但大约十年来我第一次看到一些 JavaScript HTML5 的东西 我完全被什么应该是最简单的事情难住了 作为一个例子 我只想画一些东西并为其添加一个事件处理程序 我确信我在做一些愚蠢的事情 但我已
  • iPhone模拟器和Android模拟器的区别

    iPhone模拟器和Android模拟器有什么区别 我听人们说模拟器确实模拟了目标设备 但在模拟器的情况下则不然 我认为Android模拟器模仿目标设备的处理速度 内存使用情况 但模拟器不模拟设备 免责声明 我只是一名 iPhone 开发者
  • 三星“应用程序优化”功能在 3 天后杀死后台应用程序

    我们目前正在开发一款 Android 应用程序 它是一款健身追踪器应用程序 它在后台持续运行 并且在大多数设备上运行良好 但我们一直遇到应用程序在某些三星设备上完全消失的问题 经过一番调查 似乎某些三星设备具有完全自定义的 应用程序优化 功
  • 测试两个范围是否重叠的最有效方法是什么?

    给定两个包含范围 x1 x2 和 y1 y2 其中x1 x2 and y1 y2 测试两个范围是否重叠的最有效方法是什么 一个简单的实现如下 bool testOverlap int x1 int x2 int y1 int y2 retu
  • 如何在 Django 中创建装饰器来装饰视图

    我有观点 decorator def func request hello hello return render to responce test html locals 和模板 test html hello username 我想写装
  • 如何在不注册机器人帐户的情况下以编程方式从维基共享资源下载图像?

    机器人帐户获得批准的唯一方法似乎是添加或编辑维基媒体上已有的信息 如果您尝试在没有机器人帐户的情况下使用某些 api 库下载任何图像 您会收到错误消息而不是图像 似乎他们阻止了任何不从浏览器进入的人 其他人有这方面的经验吗 我在这里错过了什
  • 提交触发后 Bitbucket 构建错误

    我试图在使用 BitBucket 插件提交时自动触发构建 我似乎使用 Web Hook 正确设置了内容 并选中项目中的 将更改推送到 BitBucket 时构建 框 当我提交时 我在 BitBucket Hook Log 中看到一条消息 显
  • 继承对象的 XML 反序列化

    我有一个对象InputFile它有数组和对象来保存文件的内容 我也有ABCFile and XYZFile两者都继承自InputFile它将读取不同类型的文件并将它们存储到的投影成员中InputFile 由于这两个对象的序列化和反序列化与父
  • Flutter Web 中的分段文件上传

    有没有办法将文件分段上传到 Flutter Web 原生的服务器 因为 Flutter iOS 和 Android 有很多方法可以做到这一点 对于 Android IOS 我们使用 multiPFile await MultipartFil
  • 无法使用 AKS 和 ACR 提取新映像

    我突然在使用 AKS 从 Azure 容器注册表中提取最新映像时遇到问题 之前工作正常 If I run kubectl describe pod
  • CodeIgniter htaccess 修改为半 https 且无 www 版本

    htaccess 修改与核心 PHP 中不同 因此 经过一番搜索 我得到了以下代码 在那之前 我的要求是我的项目的标准 整个网站严禁使用 www 即直接重定向到非 www 版本 HTTPS 适用于某些页面 结帐 登录页面 其他页面严格采用
  • Android 自定义对话框的昏暗背景

    正如标题所示 我似乎无法调暗我制作的自定义对话框的背景 网上无数的解决方案都提到了下面第一个片段中的最后 3 行代码 这对对话框的 UI 没有影响 请看下面的代码 Dialog dialog new Dialog MainActivity
  • iOS SDK中逐行读取文件

    我有一个文本文件如下 line1 line2 line3 line4 line5 我想从文件读入两个字符串数组 以便line1 line3 line 5 进入array1 and line 2 line 4 line 6 进入array2
  • 将 ISO 8601 日期时间字符串反序列化为 C# DateTime

    我正在尝试使用 JsonConvert DeserializeObject
  • 按钮动画像ios游戏中心按钮

    我正在尝试让我的按钮像 ios 游戏中心中的按钮一样具有动画效果 它们似乎像气泡一样在屏幕上摇摆和漂浮 我尝试过在屏幕上随机移动按钮 使它们同时以恒定的圆形路径移动 但效果不一样 我需要一种摇摆效果 任何想法表示赞赏 结合几个CAKeyfr
  • Scenebuilder 2.0 中的自定义组件

    在 Scenebuilder 1 1 中 您可以将整个自定义组件作为一个整体导入 然而 在 2 0 中 它将组件作为单独的部分 容器和节点 导入 由于我的自定义组件依赖于与其控制器和 ID 的统一工作 因此这会破坏它 到目前为止我能做些什么
  • 动态编译依赖于特定类加载器加载的类的java代码

    我们有能力即时动态编译 Java 代码 我至少知道Java 运行时编译器 https github com OpenHFT Java Runtime Compiler and 内存Java编译器 https github com trung