我目前正在尝试在运行时编译一个类,但出于某种原因,它只在一个系统上工作。两个系统使用完全相同的代码并安装了相同的Java版本,但是在一个系统上我的.java文件编译为.class,而在另一个系统上我得到异常,因为某些类是或应该是,在类路径中找不到。
我用来编译它的代码是:
private static File compile(File file) {
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
List<String> optionList = new ArrayList<>();
File jar = getJar(RuntimeCompiler.class);
File pluginDirectory = new File(jar.getAbsolutePath().substring(0, jar.getAbsolutePath().length() - jar.getName().length()));
String classes = buildClassPath(getJar(Bukkit.class).getAbsolutePath(), pluginDirectory.getAbsolutePath() + "/*");
optionList.addAll(Arrays.asList("-classpath",classes));
boolean success;
try (StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null )) {
Iterable<? extends JavaFileObject> units;
units = fileManager.getJavaFileObjectsFromFiles(Arrays.asList(file));
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, optionList, null, units);
success = task.call();
}
if(success) {
return new File(file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 5) + ".class");
}
else {
return null;
}
} catch (IOException ex) {
Logger.getLogger(RuntimeCompiler.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
private static String buildClassPath(String... paths) {
StringBuilder sb = new StringBuilder();
for (String path : paths) {
if (path.endsWith("*")) {
path = path.substring(0, path.length() - 1);
File pathFile = new File(path);
for (File file : pathFile.listFiles()) {
if (file.isFile() && file.getName().endsWith(".jar")) {
sb.append(path);
sb.append(file.getName());
sb.append(System.getProperty("path.separator"));
}
}
} else {
sb.append(path);
sb.append(System.getProperty("path.separator"));
}
}
String s = sb.toString();
s = s.substring(0,s.length() - 1);
return s;
}
包含必要文件的Core-1.0-SNAPSHOT.jar的classpath(optionList.toString())。
[-classpath, /usr/local/gpx/users/user/127.0.0.1:25702/spigot.jar:25702/plugins/Core-1.0-SNAPSHOT.jar]
堆栈跟踪
/usr/local/gpx/users/user/127.0.0.1:25702/plugins/debug/DebugClass.java:1: error: package net.nowcraft.core does not exist
[14:04:10] [Server thread/WARN]: import net.nowcraft.core.core;
[14:04:10] [Server thread/WARN]: ^
[14:04:10] [Server thread/WARN]: /usr/local/gpx/users/user/127.0.0.1:25702/plugins/debug/DebugClass.java:2: error: package net.nowcraft.core.RuntimeCompiler does not exist
[14:04:10] [Server thread/WARN]: import net.nowcraft.core.RuntimeCompiler.Debugger
[14:04:10] [Server thread/WARN]:
[14:04:10] [Server thread/WARN]: /usr/local/gpx/users/user/127.0.0.1:25702/plugins/debug/DebugClass.java:7: error: method does not override or implement a method from a supertype
[14:04:10] [Server thread/WARN]: @Override
[14:04:10] [Server thread/WARN]: ^
[14:04:10] [Server thread/WARN]: 3 errors
[14:04:10] [Server thread/ERROR]: null
org.bukkit.command.CommandException: Unhandled exception executing command 'rd' in plugin NowCraftCore v1.0
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:46) ~[spigot.jar:git-Spigot-330d66b-fe41b01]
at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:141) ~[spigot.jar:git-Spigot-330d66b-fe41b01]
at org.bukkit.craftbukkit.v1_8_R1.CraftServer.dispatchCommand(CraftServer.java:642) ~[spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.PlayerConnection.handleCommand(PlayerConnection.java:1115) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.PlayerConnection.a(PlayerConnection.java:950) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(PacketPlayInChat.java:26) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.PacketPlayInChat.a(PacketPlayInChat.java:53) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.PacketHandleTask.run(SourceFile:13) [spigot.jar:git-Spigot-330d66b-fe41b01]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_25]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_25]
at net.minecraft.server.v1_8_R1.MinecraftServer.z(MinecraftServer.java:683) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.DedicatedServer.z(DedicatedServer.java:316) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.MinecraftServer.y(MinecraftServer.java:623) [spigot.jar:git-Spigot-330d66b-fe41b01]
at net.minecraft.server.v1_8_R1.MinecraftServer.run(MinecraftServer.java:526) [spigot.jar:git-Spigot-330d66b-fe41b01]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_25]
Caused by: java.lang.NullPointerException
at net.nowcraft.core.RuntimeCompiler.RuntimeCompiler.load(RuntimeCompiler.java:127) ~[?:?]
at net.nowcraft.core.RuntimeCompiler.RuntimeCompiler.loadHastebin(RuntimeCompiler.java:88) ~[?:?]
at net.nowcraft.core.RuntimeCompiler.RuntimeCompiler.debugFromHastebin(RuntimeCompiler.java:170) ~[?:?]
at net.nowcraft.core.commands.RuntimeDebug.onCommand(RuntimeDebug.java:35) ~[?:?]
at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44) ~[spigot.jar:git-Spigot-330d66b-fe41b01]
... 14 more
编辑: 我也在不同的目录中测试过,没有用。当我在我的本地Windows笔记本电脑上使用该代码时,它确实可以工作。
编辑2: 这似乎是CentOS的一个问题,因为它不在第二个CentOS系统上工作。
答案 0 :(得分:1)
Stacktrace帮助极大,以及周围的环境。
这里的问题是linux。所以你想要点击的目录:
/usr/local/gpx/users/user/127.0.0.1:25702/plugins/debug/DebugClass.java
正在寻找名为127.0.0.1:25702
的目录(尽管:
必须进行转义,因为大多数shell使用:
作为语法字符。
您的网络地址将映射到特定目录。您将不得不创建网络共享(不熟悉CentOS,但通常非常简单),以消除对物理存在的位置的网络引用。如果您可以从命令行cd
,那么您的Java运行时应该能够实际引用它。
Here is a reference用于在CentOS上安装远程文件系统。是的,我知道127.0.0.1:25702
在技术上是&#34; localhost&#34;但是命令shell和java运行时都不知道如何以你想要的方式解析网络地址。它适用于Windows,因为Windows API更宽容。
答案 1 :(得分:0)
我猜你在本地使用Windows而unix用于远程服务器? unix机器上java的classpath分隔符是“:”,你有一个名称中带有“:”的目录,unix编译器可能会用“:”分割目录名。您是否尝试在文件/目录名称中不包含“:”的非工作计算机上使用类路径?