我对模块化 Java 的兴趣已经几个月了,包括 Spring 和相关的生态系统内容。最令人沮丧的经历之一是调试名称不明确的模块问题
这是我遇到的最后一个此类错误:
java.lang.IllegalAccessError: superclass access check failed: class com.oracle.truffle.polyglot.PolyglotImpl (in unnamed module @0x58a90037) cannot access class org.graalvm.polyglot.impl.AbstractPolyglotImpl (in module org.graalvm.sdk) because module org.graalvm.sdk does not export org.graalvm.polyglot.impl to unnamed module @0x58a90037
@0x58a90037问题就在这里。
根据我要做的事情,我会随机尝试spring.beans,spring.context等等javax.validation......并向世界开放我的模块,这在某种程度上消除了首先封装它们的价值。
对于这个具体案例,我尝试过虽然进展并不顺利,但还是requires org.graalvm.sdk;requires org.graalvm.js;做到了。
通过随机尝试进行调试似乎并不是解决这些问题的明智方法。所以我想知道你们是怎么做到的。
谢谢你!
我的问题:在构建最小的 JRE 时,如何确保没有缺少所需的模块?
为了说明这个问题,这里有一个例子,我想为我的项目构建一个最小的 JRE。在此示例中,我们假设 logback 是我唯一的依赖项。
我运行以下命令来查看需要哪些模块:
$ jar --file=logback-core-1.2.3.jar --describe-module
No module descriptor found. Derived automatic module.
logback.core@1.2.3 automatic
requires java.base mandated
contains ch.qos.logback.core
contains ch.qos.logback.core.boolex
etc. (there are more "contains ch.qos.logback.XXX" lines)
Run Code Online (Sandbox Code Playgroud)
看来我只需要该java.base模块,并相应地构建了我的最小 JRE:
jlink --output jre-min --add-modules java.base
Run Code Online (Sandbox Code Playgroud)
然而,当使用最小的 JRE 运行项目时,我在使用 logback 的电子邮件记录器时遇到了问题(通过 TLS 的格式错误的电子邮件)。经过反复试验,我发现jdk.crypto.cryptoki还需要该模块:
jlink --output jre-min --add-modules java.base,jdk.crypto.cryptoki
Run Code Online (Sandbox Code Playgroud)
现在我的项目运行良好。我怎样才能避免试错步骤?
我有一个简单的 JavaFX Web 浏览器,它是一个模块。该模块的目录结构为:
webBrowser
webBrowser/module-info.java
webBrowser/webbrowser
webBrowser/webbrowser/WebBrowser.java
Run Code Online (Sandbox Code Playgroud)
这是 module-info.java 的代码
module webBrowser {
requires javafx.controls;
requires javafx.web;
exports webbrowser;
}
Run Code Online (Sandbox Code Playgroud)
以下是 WebBrowser.java 的代码:
package webbrowser;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.scene.web.WebEngine;
import javafx.stage.Stage;
public class WebBrowser extends Application {
@Override
public void start(Stage stage) {
WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.load("http://www.oracle.com");
Scene scene = new Scene(browser, 1200, 900);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
Run Code Online (Sandbox Code Playgroud)
我用 javac 编译我的模块化应用程序: …
我有一个服务器工具包,我试图在java9 JDK上测试(在这里找到,我使用的是64位Linux版本),但是我在启动后不久遇到以下错误:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:533)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:186)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:476)
Run Code Online (Sandbox Code Playgroud)
使用java8时,服务器套件启动时没有问题.不知怎的,我需要告诉运行时系统包含javax.xml.bind模块,但是我是java9的新手,并且不知道如何将整个服务器工具包重新编译成模块并在javax.xml.bind模块上添加依赖项.有没有办法解决这个错误,不需要我重新编译服务器工具包到模块?
我有三个模块:module-a,module-b,module-c.模块-a和模块-b在引导层中.模块-c的层我自己创建.Module-c具有服务的JPMS实现,其接口在module-a中.
这是我在module-b中使用module-c创建图层的方式.
ModuleFinder finder = ModuleFinder.of(moduleCPath);
ModuleLayer parent = ModuleLayer.boot();
Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("module-c"));
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl);
Run Code Online (Sandbox Code Playgroud)
然后在module-b中我从module-c调用服务.服务执行完成后,我不再需要module-c和new created layer了.如何从JVM中删除它并释放所有资源?这样做够了吗layer = null;?
我正在回答这个问题,我建议使用exports to语法来防止外部消费者访问模块之间内部使用的代码.
但是在进一步思考时,模块实现的唯一真正的安全检查是它与名称匹配.考虑这个我正在实现两个模块的例子:
module a {
exports unsafe to b
}
module b {
requires a
}
Run Code Online (Sandbox Code Playgroud)
该软件包unsafe包含暴露不安全的代码.有没有办法将其安全地导出到内部模块而不将其暴露在外部?
在上面的示例中,流氓实体可以简单地命名其模块b并获得对代码的访问(不安全).该JLS似乎并没有阐明任何可以阻止它.
我正在写一个module-info.java为Ikonli的Fontawesom5模块,org.kordamp.ikonli.fontawesome5。该jar有一些需要访问的资源:https : //github.com/aalmiray/ikonli/tree/master/subprojects/ikonli-fontawesome5-pack/src/main/resources/META-INF/resources/fontawesome5/5.0 .1
如何为这些资源添加exports或,opens以便其他模块可以加载它们?我试过了:
exports fonts;
Run Code Online (Sandbox Code Playgroud)
和
exports fontawesome5.fonts;
Run Code Online (Sandbox Code Playgroud)
和
exports fontawesome5.5.0.1.fonts;
Run Code Online (Sandbox Code Playgroud)
但是当我链接整个应用程序时,它们都抛出相同的错误:
Error reading module: C:\Users\pupeno\Documents\Dashman\code\dashman\target\modules\ikonli-fontawesome5-pack-2.3.0.jar
Run Code Online (Sandbox Code Playgroud)
导出这些资源的正确语法是什么?
用
module org.kordamp.ikonli.fontawesome5 {
exports org.kordamp.ikonli.fontawesome5;
provides org.kordamp.ikonli.IkonHandler with org.kordamp.ikonli.fontawesome5.FontAwesomeBrandsIkonHandler, org.kordamp.ikonli.fontawesome5.FontAwesomeRegularIkonHandler, org.kordamp.ikonli.fontawesome5.FontAwesomeSolidIkonHandler;
}
Run Code Online (Sandbox Code Playgroud)
这些是该jar中的模块:
>java -p target\modules\ikonli-fontawesome5-pack-2.3.0.jar --list-modules
java.activation@10.0.1
java.base@10.0.1
java.compiler@10.0.1
java.corba@10.0.1
java.datatransfer@10.0.1
java.desktop@10.0.1
java.instrument@10.0.1
java.jnlp@10.0.1
java.logging@10.0.1
java.management@10.0.1
java.management.rmi@10.0.1
java.naming@10.0.1
java.prefs@10.0.1
java.rmi@10.0.1
java.scripting@10.0.1
java.se@10.0.1
java.se.ee@10.0.1
java.security.jgss@10.0.1
java.security.sasl@10.0.1
java.smartcardio@10.0.1
java.sql@10.0.1
java.sql.rowset@10.0.1
java.transaction@10.0.1
java.xml@10.0.1
java.xml.bind@10.0.1
java.xml.crypto@10.0.1
java.xml.ws@10.0.1
java.xml.ws.annotation@10.0.1
javafx.base@10.0.1
javafx.controls@10.0.1 …Run Code Online (Sandbox Code Playgroud) ---------------------------------------------
package org.zpf.service;
public interface Services {
void test();
}
module org.zpf.service.Services {
exports org.zpf.service;
}
---------------------------------------------
package org.zpf.impl;
import org.zpf.service.Services;
public class Impl implements Services {
@Override
public void test() {
System.out.println("Impl-1");
}
}
module org.zpf.impl.Impl {
requires org.zpf.service.Services;
provides org.zpf.service.Services with org.zpf.impl.Impl;
}
----------------------------------------------
public class Demo {
public static void main(String[] args) {
ServiceLoader.load(Services.class).forEach(Services::test);
}
}
module org.zpf.demo.Demo {
requires org.zpf.service.Services;
uses org.zpf.service.Services;
}
Run Code Online (Sandbox Code Playgroud)
我使用IntelliJ IDEA运行此代码,但看起来子模块未运行.以下是程序的输出:
/Library/Java/JavaVirtualMachines/jdk-11.0.1.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA 2018.3.app/Contents/lib/idea_rt.jar=61434:/Applications/IntelliJ IDEA 2018.3.app/Contents/bin" -Dfile.encoding=UTF-8 -p /Users/tubetrue01/IDEA/Test/Demo/target/classes:/Users/tubetrue01/IDEA/Test/Services/target/classes -m org.zpf.demo.Demo/org.zpf.demo.Demo …Run Code Online (Sandbox Code Playgroud) 我想要使用sun.awt.image.PNGImageDecoder在我的项目中使用的一些代码.问题是源代码基于Java 8和我的项目使用JDK 9+(11).所以我收到了这个错误:
包'
sun.awt.image'在模块'java.desktop'中声明,它不会将其导出到未命名的模块.
为import sun.awt.image.*,和:
符号在模块'
java.desktop'中声明,它不导出包'sun.awt.image'
使用PNGImageDecoder或ImageDecoder等
在寻找解决方案的一些努力之后,我发现了一些类似的情况,建议添加requires java.desktop;到module-info.java文件(像这种情况和这种情况).但是当我意识到这个解决方案只有在你的项目已经有一个module-info.java文件并且你遗漏了一个用过的模块时才有用.
我的项目已经没有此文件(请注意第一条错误消息中的" 未命名模块 ").据我所知,这意味着所有模块都是自动导入的.所以添加这个文件并添加该行没有任何影响,除了(更改错误消息和)导致我的代码的其他部分出现一些类似的问题(当然,这可以通过向module-info.java文件添加所需的模块来解决).
确保我在jmods文件夹(JDK 11)中导入了所有模块,但问题没有解决:
requires java.base;
requires java.compiler;
requires java.datatransfer;
requires java.desktop;
requires java.instrument;
requires java.logging;
requires java.management;
requires java.management.rmi;
requires java.naming;
requires java.net.http;
requires java.prefs;
requires java.rmi;
requires java.scripting;
requires java.se;
requires …Run Code Online (Sandbox Code Playgroud) java java-platform-module-system java-9 java-module module-info
java-module ×10
java ×9
java-9 ×6
java-platform-module-system ×2
jlink ×2
java-17 ×1
javafx ×1
jls ×1
module-info ×1
module-path ×1
service ×1