Невозможно программно скомпилировать исходный код Java из строки в Linux - PullRequest
0 голосов
/ 20 января 2019

Я компилирую классы Java из строки и, по какой-то причине, однако, я делаю, это прекрасно работает в Windows, но выдает исключение NullPointerException в Linux.

Я пытался поискать в Google, но не могу найти ничего, даже отдаленно связанного с этим.

Вот трассировка стека:

java.lang.RuntimeException: java.lang.NullPointerException
    at com.sun.tools.javac.main.Main.compile(Main.java:559)
    at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
    at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138) //This is where the compiler task gets called
    at mekanism.common.network.PacketSecurityUpdate.invalidUsername(PacketSecurityUpdate.java:140)
    at mekanism.common.network.PacketSecurityUpdate$SecurityUpdateMessage.fromBytes(PacketSecurityUpdate.java:89)
    at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:17)
    at cpw.mods.fml.common.network.simpleimpl.SimpleIndexedCodec.decodeInto(SimpleIndexedCodec.java:7)
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:77)
    at cpw.mods.fml.common.network.FMLIndexedMessageToMessageCodec.decode(FMLIndexedMessageToMessageCodec.java:17)
    at io.netty.handler.codec.MessageToMessageCodec$2.decode(MessageToMessageCodec.java:81)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:89)
    at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111)
    at io.netty.channel.DefaultChannelHandlerContext.invokeChannelRead(DefaultChannelHandlerContext.java:337)
    at io.netty.channel.DefaultChannelHandlerContext.fireChannelRead(DefaultChannelHandlerContext.java:323)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:785)
    at io.netty.channel.embedded.EmbeddedChannel.writeInbound(EmbeddedChannel.java:169)
    at cpw.mods.fml.common.network.internal.FMLProxyPacket.func_148833_a(FMLProxyPacket.java:77)
    at net.minecraft.network.NetworkManager.func_74428_b(NetworkManager.java:245)
    at net.minecraft.network.NetworkSystem.func_151269_c(NetworkSystem.java:181)
    at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:1023)
    at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:432)
    at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:841)
    at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:693)
    at java.lang.Thread.run(Thread.java:748)
  Caused by: java.lang.NullPointerException
    at com.sun.tools.javac.api.ClientCodeWrapper.isTrusted(ClientCodeWrapper.java:189)
    at com.sun.tools.javac.api.ClientCodeWrapper.wrap(ClientCodeWrapper.java:133)
    at com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileManager.getJavaFileForOutput(ClientCodeWrapper.java:309)
    at com.sun.tools.javac.jvm.ClassWriter.writeClass(ClassWriter.java:1615)
    at com.sun.tools.javac.main.JavaCompiler.genCode(JavaCompiler.java:746)
    at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1572)
    at com.sun.tools.javac.main.JavaCompiler.generate(JavaCompiler.java:1536)
    at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    ... 23 more

Вот код, который я использую

    public static final JavaCompiler JAVAC;

    static {
        String h = System.getProperty("java.home");
        if (!h.endsWith("jre")) {
            h = h.replace("jre", "jdk") + File.separator + "jre";
            System.setProperty("java.home", h);
        }
        System.out.println(System.getProperty("java.home"));
        JAVAC = ToolProvider.getSystemJavaCompiler();
    }

    public static class JavaClass extends SimpleJavaFileObject {

        private ByteArrayOutputStream baos = new ByteArrayOutputStream();

        public JavaClass(String className) {
            super(getUri(className), Kind.CLASS);
        }

        private static final URI getUri(String className) {
            try {
                return new URI(className);
            } catch (URISyntaxException e) {
                throw new RuntimeException("Could not parse URI", e);
            }
        }

        @Override
        public OutputStream openOutputStream() throws IOException {
            return baos;
        }

        public byte[] getByteCode() {
            return baos.toByteArray();
        }

    }

    public static class JavaClassLoader extends ClassLoader {

        private final Map<String, JavaClass> classes = new HashMap<>();

        public JavaClassLoader(ClassLoader classLoader) {
            super(classLoader);
        }

        public JavaClass getClass(String name) {
            return classes.get(name);
        }

        public JavaClassLoader addClass(JavaClass cc) {
            classes.put(cc.getName(), cc);
            return this;
        }

        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            JavaClass cc = classes.get(name);
            if (cc == null) {
                return super.findClass(name);
            }
            byte[] byteCode = cc.getByteCode();
            return defineClass(name, byteCode, 0, byteCode.length);
        }

    }

    public static class FileManager extends ForwardingJavaFileManager<JavaFileManager> {

        private static final StandardJavaFileManager STANDARD_JAVA_FILE_MANAGER = JAVAC.getStandardFileManager(null, null, null);

        private JavaClassLoader classLoader = new JavaClassLoader(Test.class.getClassLoader());

        public FileManager(String className) {
            super(STANDARD_JAVA_FILE_MANAGER);
            this.classLoader.addClass(new JavaClass(className));
        }

        public JavaClassLoader getClassLoader() {
            return classLoader;
        }

        @Override
        public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
            return classLoader.getClass(className);
        }

        public byte[] getBytecode(String className) {
            return classLoader.getClass(className).getByteCode();
        }

        public Class<?> loadClass(String className) throws ClassNotFoundException {
            return classLoader.loadClass(className);
        }

    }

    public static class JavaSource extends SimpleJavaFileObject {

        private final String code;

        public JavaSource(String name, String code) {
            super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return code;
        }

    }


    public static void main(String[] args) throws Exception {
        String className = //Class name
        String code = //Code

        JavaSource sourceCode = new JavaSource(className, code);
        FileManager fileManager = new FileManager(className);
        JAVAC.getTask(null, fileManager, null, null, null, Arrays.asList(sourceCode)).call();
    }

1 Ответ

0 голосов
/ 20 января 2019

@ Комментарий MadProgrammer позволил мне понять, что я забыл.Домашнее исправление java относится только к Windows

    static {
        if (System.getProperty("os.name").toLowerCase().contains("windows")) { //Added this check
            String h = System.getProperty("java.home");
            if (!h.endsWith("jre")) {
                h = h.replace("jre", "jdk") + File.separator + "jre";
                System.setProperty("java.home", h);
            }
        }
        JAVAC = ToolProvider.getSystemJavaCompiler();
    }
...