- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在生成.java
类文件在运行时生成,并且需要立即在代码中使用这些类。所以我编译了.java
使用编译器 API 来制作 .class
的类文件:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
StandardJavaFileManager manager = compiler.getStandardFileManager(diagnostics, null, null);
File file = new File("path to file");
Iterable<? extends JavaFileObject> sources = manager.getJavaFileObjectsFromFiles(Arrays.asList(file));
CompilationTask task = compiler.getTask(null, manager, diagnostics, null, null, sources);
task.call();
manager.close();
然后我需要使用 Class.forName()
获取对这些已编译类的引用,但是如果我打电话Class.forName("com.foo.Bar")
它抛出 ClassNotFoundException
,假设是因为新的.class
文件未添加到 classpath
我寻找向 classpath
添加类的方法在运行时。我遇到了一些与这个概念相关的歧义:
1. 这种方法(首先使用编译器 API 编译 .java
文件,然后在第二步将其添加到类加载器中)是否正确?能够立即在代码中使用该类。
2. AFAIK,有两种方法可以在运行时将类动态加载到类路径中:一种是使用像这样的自定义类加载器:(我编译时出错,因为它提示 BuiltinClassLoader
没有 addURL
方法):
// Get the ClassLoader class
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class<?> clazz = cl.getClass();
// Get the protected addURL method from the parent URLClassLoader class
Method method = clazz.getSuperclass().getDeclaredMethod("addURL", new Class[] { URL.class });
// Run projected addURL method to add JAR to classpath
method.setAccessible(true);
method.invoke(cl, new Object[] { cls });
另一种方法是使用Class.forName(name, instantiation, classLoader)
将类添加到类路径(同时也给出类引用)。由于如上所述出现编译器错误(Java 11),我无法应用第一种方法。关于第二种方法,会Class.forName(name, instantiation, classLoader)
将新类附加到 classpath
如果我们像这样调用默认类加载器? :
Class.forName("com.foo.Bar",true, ClassLoader.getSystemClassLoader());
// or:
Class.forName("com.foo.Bar",true, ApiHandler.class.getClassLoader());
这对我不起作用。上述类加载器参数的哪种变体是正确的,为什么这些不起作用?是否必须创建自定义类加载器并将其传递给 Class.forName()
?
3.我正在制作 .java
com.foo
内的文件封装在 src
eclipse 项目的文件夹。他们编译的.class
文件也会在同一文件夹中生成(使用编译器 API)。当我使用 eclipse 刷新项目时(右键单击项目 -> 刷新)相关的 .class
文件将在 target/classes
中生成文件夹中,此时可以通过代码访问类(例如使用 Class.forName("com.foo.Bar)
。如果我在 .class
文件夹中生成 target/classes
文件(通过编译器 API),这些类将无需识别即可识别将它们引入类路径?
更新:
通过保存受人尊敬的.class
,我能够在我的代码中使用编译后的类。文件在 target/classes
项目的上面第三个问题中提到的文件夹。 (通过将 -d
选项添加到编译器的 getTask()
方法中:
Iterable<String> options = Arrays.asList( new String[] { "-d", System.getProperty("user.dir") + "/target/classes/"} );
.
.
.
CompilationTask task = compiler.getTask(null, manager, diagnostics, options, null, sources);
这样,似乎甚至不需要使用 classLoader 将类添加到类路径;因为可以使用简单的 Class.forName()
访问该类。 你如何解释这一点?
Class<?> cls1 = Class.forName("com.foo.Bar");
当然,也可以通过 ClassLoader 方式:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class<?> cls = classLoader.loadClass("com.foo.Bar");
最佳答案
最安全的解决方案是创建一个新的 ClassLoader
实现并通过新的加载器加载生成的类,如this answer所示.
但是从 Java 9 开始,如果尚未定义/加载具有该名称的类,则可以在您自己的上下文中(即在同一包中)定义类。如上所述,这样的类定义甚至可以取代类路径上的定义,只要它尚未加载。因此,不仅后续的 Class.forName(String) 调用将解析为此类定义,甚至非反射引用也会解析为该类定义。
这可以通过以下程序进行演示。
class Dummy { // to make the compiler happy
static native void extensionMethod();
}
public class CompileExtension {
public static void main(String[] args) throws IOException, IllegalAccessException {
// customize these, if you want, null triggers default behavior
DiagnosticListener<JavaFileObject> diagnosticListener = null;
Locale locale = null;
// the actual class implementation, to be present at runtime only
String class1 =
"class Dummy {\n"
+ " static void extensionMethod() {\n"
+ " System.out.println(\"hello from dynamically compiled code\");\n"
+ " }\n"
+ "}";
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,
Set.of(Files.createTempDirectory("compile-test").toFile()));
JavaCompiler.CompilationTask task = c.getTask(null, fm,
diagnosticListener, Set.of(), Set.of(),
Set.of(new SimpleJavaFileObject(
URI.create("string:///Class1.java"), JavaFileObject.Kind.SOURCE) {
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
return class1;
}
}));
if(task.call()) {
FileObject fo = fm.getJavaFileForInput(
StandardLocation.CLASS_OUTPUT, "Dummy", JavaFileObject.Kind.CLASS);
// these are the class bytes of the first class
byte[] classBytes = Files.readAllBytes(Paths.get(fo.toUri()));
MethodHandles.lookup().defineClass(classBytes);
Dummy.extensionMethod();
}
}
}
Dummy
定义的存在只是为了能够在编译时插入对所需方法的调用,而在运行时,动态定义的类会在方法被调用之前取代它的位置。
但请小心处理。如前所述,自定义类加载器是最安全的解决方案。通常,您应该通过始终存在的接口(interface)创建对扩展的编译时引用,并且仅动态加载实现,可以在运行时将其强制转换为接口(interface),然后通过接口(interface)定义的 API 使用。
关于java - Class.forName(name, instantiation, classLoader) 不会将类添加到类路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56233744/
BufferedImage image = ImageIO.read(SpriteSheet.class.getResource(path)); BufferedImage image = Image
希望有人能够帮助我解决将我的 React 应用程序推送到 Heroku 时遇到的问题。 heroku 日志反复显示以下错误。 at=error code=H10 desc="App crashed"
我是 Kotlin 的新手,我正在经历这样的例子。 . . package com.example.lambda1 import spark.Spark.get fun main(args: Arra
如果您已经安装了 32 位 JDK,请在中定义一个 JAVA_HOME 变量 Computer>System Properties>System Setting>Enviorment VAriable
我正在开发一个独立于平台的应用程序。我收到一个文件 URL*。在 Windows 上,这些是: file:///Z:/folder%20to%20file/file.txt file://host/f
我在 OSX、Objective-C 上。 我有一个像 这样的路径/NSURL /Users/xxx/Desktop/image2.png 但我将它传递给第三方应用程序,该应用程序会像 excpect
我已经安装了 Android studio 和插件的 DART,FLUTTER 来启动 flutter,但是因为我在创建我的第一个 flutter 项目时无法提供 sdk 路径。 最佳答案 我试图找出
127.0.0.1:8000/api/仅包含来自第二个应用程序的 url,但我将两个 url 模块链接到相同的模式。甚至有可能做到这一点吗? 第一个应用程序: from django.urls imp
对于大量图像(大约 1k,加上相同数量的拇指,在大约 500 个文件夹中),我们要求网站上使用的所有图像 URI 都必须具有 SEO 优化路径。它们已经准备好并提供完整的路径结构(每个文件夹包含一个具
为什么 f 不是一个文件?什么可能导致这种情况? String currentPhotoPath = "file:/storage/sdcard0/Pictures/someFileName.
Gradle 中的项目名称或路径中允许使用哪些字符? 它是否与特定操作系统的目录名称中允许的字符相同(例如: http://en.wikipedia.org/wiki/Filename#Reserve
我有一个包含文件夹路径的表格。我需要找到层次结构中这些文件夹之间的所有“差距”。我的意思是,如果表格包含这 3 个文件夹: 'A' 'A\B\C' 'A\B\C\D\E\F\G' 我需要在层次结构中找
我在 Linux 服务器上的/home/subversion 中安装了 svn - 那里有一个 ROOT 文件夹,其中包含 db 和 conf 等文件夹。没有映射到项目名称的文件夹,请有人告诉我如何列
对于我的图像位置:/src/assets/bitmap/sample.jpg 给出了关键配置: context: resolve('src') output: { path: resolve('b
我需要创建带有圆角的 SVG 路径,以将它们导出到 DXF 进行切割。我的问题是角应该是圆弧,而不是贝塞尔曲线。 使用 arc 命令相对容易处理直角,因为半径也是从拐角到圆弧起点的距离。对于其他角度,
大家好,我正在玩 Airflow,我正在阅读这篇很有帮助的 tutorial .我正在寻求帮助以更好地了解 Admin->Connection 如何在 Conn Type: File (path) 方
我的目标是定义R将用于安装和搜索库的单个路径。我read可以通过更改Rprofile.site安装路径中的R文件来完成。我在那里尝试了两个命令: .libPaths("D:/RLibrary") .L
我有一个问题:当我在一个页面中时,我想返回到上一页。我使用 $routeProvider。如何读取之前的 url? 我尝试在我的 Controller 中使用此代码但不起作用... angular.m
我正在尝试将一个文件从我的主干合并到一个分支(wc),并且对于看起来位于当前合并操作中不涉及的分支上的路径出现奇怪的未找到路径错误。 例如,在我们的 svn 项目中,我们有: 分行 分支 0 分支 1
我有一个树数据序列化如下: 关系:P到C是“一对多”,C到P是“一对一”。所以列 P 可能有重复的值,但列 C 有唯一的值。 P, C 1, 2 1, 3 3, 4 2, 5 4, 6 # in da
我是一名优秀的程序员,十分优秀!