问题
I am currently trying to successfully extract the java.base.java.util.jar package from the jdk-9.0.1, building a .jar out of it and importing the jar as external library into another project, so that I can modify the behavior of some of the methods from the classes contained in it.
I seem to be successful at extracting the package, as I am able to eradicate all possible pre-compilation-errors in the project and build the .jar artifact. I can also import this .jar as external library in my other project.
Edit: every private class from outside java.util.jar (i.e.: SharedSecrets) that was needed was also extracted and put in the .jar
However, when I try to run it (by replacing the import java.util.jar.*;
in order to use my own version of it)
I get this error: java.lang.IllegalAccessError: class SharedSecrets (in unnamed module @0x2b546384) cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @0x2b546384
I tried both adding this: --add-exports=java.base/jdk.internal.misc=ALL-UNNAMED
and adding this: --add-exports=java.base/jdk.internal.misc.Unsafe=ALL-UNNAMED
to the Compilation options of both, the project consisting of the extracted java.util.jar package and the project I want to import it as external library, none worked -> the error persists.
All other --add-exports
which are in the Compilation Options do work fine on both projects.
What am I doing wrong? What do I have to change in order for it to work?
N.B.: if things are unclear, feel free to ask!
Edit: The code where I try to use my own 'java.util.jar' instead of the official one (note at the moment both are identical, the only difference is that one remains inside the jdk while the other is just the 'minimal viable product')
This is not a duplicate of this as I (and I already pointed that out) tried the --add-exports
which are suggested as answer in the other question.
The error occurs in the 4. line where the JarFile constructor is called which will not call the one from the jdk but the one from the selfmade library I imported.
public boolean verifyJar(String jarName)
throws Exception {
boolean anySigned = false; // if there exists entry inside jar signed
Map<String, String> digestMap = new HashMap<>();
Map<String, PKCS7> sigMap = new HashMap<>();
try (JarFile jf = new JarFile(jarName, true)) { // error
Vector<JarEntry> entriesVec = new Vector<>();
byte[] buffer = new byte[8192];
Enumeration<JarEntry> entries = jf.entries();
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
entriesVec.addElement(je);
try (InputStream is = jf.getInputStream(je)) {
String name = je.getName();
if (MySignatureFileVerifier.isSigningRelated(name)
&& MySignatureFileVerifier.isBlockOrSF(name)) {
String alias = name.substring(name.lastIndexOf('/') + 1,
name.lastIndexOf('.'));
try {
if (name.endsWith(".SF")) {
Manifest sf = new Manifest(is);
for (Object obj : sf.getMainAttributes().keySet()) {
String key = obj.toString();
if (key.endsWith("-Digest-Manifest")) {
digestMap.put(alias,
key.substring(0, key.length() - 16));
break;
}
}
} else {
sigMap.put(alias, new PKCS7(is));
}
} catch (IOException ioe) {
throw ioe;
}
} else {
while (is.read(buffer, 0, buffer.length) != -1) {
// we just read. this will throw a SecurityException
// if a signature/digest check fails.
}
}
}
}
Manifest man = jf.getManifest();
boolean hasSignature = false;
if (man != null) {
Enumeration<JarEntry> e = entriesVec.elements();
while (e.hasMoreElements()) {
JarEntry je = e.nextElement();
String name = je.getName();
hasSignature = hasSignature
|| MySignatureFileVerifier.isBlockOrSF(name);
CodeSigner[] signers = getCodeSigners(je, sigMap.get("SIGNER"));
boolean isSigned = (signers != null);
anySigned |= isSigned;
}
}
if (man == null) {
System.out.println();
}
// Even if the verbose option is not specified, all out strings
// must be generated so seeWeak can be updated.
if (!digestMap.isEmpty()
|| !sigMap.isEmpty()) {
for (String s : digestMap.keySet()) {
PKCS7 p7 = sigMap.get(s);
if (p7 != null) {
String history;
try {
SignerInfo si = p7.getSignerInfos()[0];
X509Certificate signer = si.getCertificate(p7);
String digestAlg = digestMap.get(s);
String sigAlg = AlgorithmId.makeSigAlg(
si.getDigestAlgorithmId().getName(),
si.getDigestEncryptionAlgorithmId().getName());
PublicKey key = signer.getPublicKey();
PKCS7 tsToken = si.getTsToken();
if (tsToken != null) {
SignerInfo tsSi = tsToken.getSignerInfos()[0];
X509Certificate tsSigner = tsSi.getCertificate(tsToken);
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo);
PublicKey tsKey = tsSigner.getPublicKey();
String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName();
String tsSigAlg = AlgorithmId.makeSigAlg(
tsSi.getDigestAlgorithmId().getName(),
tsSi.getDigestEncryptionAlgorithmId().getName());
}
} catch (Exception e) {
throw e;
}
}
}
}
System.out.println();
if (!anySigned) {
if (hasSignature) {
System.out.println("jar.treated.unsigned");
} else {
System.out.println("jar.is.unsigned");
return false;
}
} else {
System.out.println("jar.verified.");
return true;
}
return false;
} catch (Exception e) {
throw e;
}
}
回答1:
As pointed out by Nicolai's answer to this question --add-exports java.base/jdk.internal.misc=ALL-UNNAMED
has to be done when compiling (javac) and when running (java) the code.
回答2:
A little late, but I since I bumped into this issue when trying out the OpenCV tutorial for Java and JavaFX, I will share what worked for me.
- To be able to compile I needed to add the OpenJFX and OpenCV libraries to classpath
- Not necessary to configure special module compilation - Eclipse handles it well with Java 11
- To be able to run I created a launch shortcut that adds the VM arguments as below
--module-path /javafx-sdk-11.0.2/lib
--add-modules=javafx.controls,javafx.fxml
--add-exports java.base/jdk.internal.misc=ALL-UNNAMED
来源:https://stackoverflow.com/questions/53633788/java-lang-illegalaccesserror-cannot-access-class-because-module-does-not-export