Illegal reflective access in an applet with Jaxb and JDK 9 [duplicate] - java

This question already has answers here:
Proper fix for Java 10 complaining about illegal reflection access by jaxb-impl 2.3.0?
(4 answers)
Closed 2 years ago.
I have a Java applet which provides a GUI to invoke a web service. It uses Jaxb to parse the XML data and unmarshall it into objects. It runs correctly with Java 1.5 to 1.8. With Java 9, not so much.
I use a container HTML to launch it in Internet Explorer 8 + JDK 9:
<applet code="com.blah.MyApplet" archive="myFatJarWithDependencies.jar" mayscript>
<param name="cache_option" value="no" />
</applet>
The applet loads fine and seems to work; however, once I connect to the web service, it kind of stops working. I have narrowed it down to this code fragment (where Foo is an auto-generated class with XML bind annotations):
System.out.println("1");
JAXBContext jc = JAXBContext.newInstance(Foo.class);
System.out.println("2");
Java's console shows the 1, and then... nothing: it doesn't crash, the applet is still responsive to mouse clicks, it doesn't throw any exceptions... there seems to be no error at all. Except for the fact that it doesn't do anything with the received data, and it never outputs the 2. I've tried alternative JAXBContext.newInstance methods (with a package name, with a package name plus a class loader), but they all do the same.
If I run the project from Eclipse Oxygen with the same JDK 9, it does work. When I connect to the web service, it outputs a few warnings, including these:
WARNING: Illegal reflective access by com.sun.xml.bind.v2.runtime.reflect.opt.Injector
(file:/C:/.../.m2/repository/com/sun/xml/bind/jaxb-impl/2.0/jaxb-impl-2.0.jar) to method
java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int)
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access
operations
But then it goes on and loads the data (and outputs the 2 to the console). My guess is it's the same problem, even if the warnings are not shown in the Java console. Maybe the JDK defaults to --illegal-access=deny when it's being run from IE? Or "silently-deny-so-the-user-dont-have-a-clue-on-whats-happening"...
Is there any way in which I can pass the --illegal-access=permit option to the JVM? (Keep in mind that I'm not directly invoking the JVM, I only have an <applet> html tag)
Is there any other way to make it work? Perhaps add something extra in my applet's manifest file? (Which, by the way, looks like this):
Manifest-Version: 1.0
Build-Jdk: 1.8.0_144
Application-name: Blah
Permissions: all-permissions
Sealed: true
Name: blah/Blah.class
SHA-256-Digest: kpf244234234..ahjsdfksf=
...
These are the Jaxb dependencies I was using originally:
javax.xml.bind : jaxb-api : 2.0
com.sun.xml.bind : jaxb-impl : 2.0
com.sun.xml.bind : jaxb-xjc : 2.0
I tried updating them from v2.0 to v2.3.0, which are supposed to be compatible with Java 9:
javax.xml.bind : jaxb-api : 2.3.0
com.sun.xml.bind : jaxb-impl : 2.3.0
com.sun.xml.bind : jaxb-core : 2.3.0
com.sun.xml.bind : jaxb-xjc : 2.3.0
But the problem still persists. Also tried these after nullpointer's answer, with no luck either:
javax.xml.bind : jaxb-api : 2.1
javax.xml : jaxb-impl : 2.1
removed the jaxb-xjc, apparently it's not needed...

Maybe the JDK defaults to --illegal-access=deny when it's being run from IE?
No, the current default mode of JDK is permit only.
--illegal-access=permit opens each package in each module in the
run-time image to code in all unnamed modules, i.e., to code on the
class path, if that package existed in JDK 8. This enables both static
access, i.e., by compiled bytecode, and deep reflective access, via
the platform's various reflection APIs.
The first reflective-access operation to any such package causes a
warning to be issued, but no warnings are issued after that point.
This single warning describes how to enable further warnings. This
warning cannot be suppressed.
This mode is the default in JDK 9. It will be phased out in a future
release and, eventually, removed.
Is there any other way to make it work?
For using the jaxb-api would suggest you follow this answer to make sure that your module uses the javax.xml.bind:jaxb-api:2.3.0 instead of com/sun/xml/bind/jaxb-impl/2.0/jaxb-impl-2.0.jar as seen in your logs.
You can configure the maven-compiler-plugin:3.7.0 as stated in the documentation here to compile sources from 1.5 to JDK 8 in different execution and JDK in alternate execution.

Related

Java 11 internal ssl security provider compilation failure [duplicate]

This question already has answers here:
Legacy Java code use of com.sun.net.ssl.internal.ssl.Provider()
(3 answers)
Closed 2 years ago.
I'm migrating an old Java(Maven) project to Java 11. I've changed the pom.xml to support Java 11 (maven compiler plugin with <release>11<release>) and executed mvn clean compile to see whether the code compiles.. but it fails on a line which refers ssl provider from com.sun.net package
java.security.Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider())
The compilation error message is as follows
[ERROR]
/D:/Workspace/sampler/src/com/sampler/test/cloudtest/CloudTest.java:[32,70]
package com.sun.net.ssl.internal.ssl is not visible (package
com.sun.net.ssl.internal.ssl is declared in module java.base, which
does not export it)
Please help me to resolve this by providing proper ssl provider in Java11.
This was removed as a part of this bug https://bugs.openjdk.java.net/browse/JDK-8218932:
Clean up the code and remove the internal package com.sun.net.ssl.
Note that an application may still use the name "com.sun.net.ssl.internal.ssl.Provider" as the SunJSSE provider name. For compatibility, the name is still supported in the JDK. The actual implementation refers to the sun.security.ssl.SunJSSE class.
With this update, the SunJSSE provider can be specified with one of the following names:
SunJSSE
com.sun.net.ssl.internal.ssl.Provider
Both "SunJSSE" and "com.sun.net.ssl.internal.ssl.Provider" are existing names.

How to modify the AST using Java 9+ [duplicate]

This question already has answers here:
Accessing com.sun.tools.javac.util from Java 9
(2 answers)
Closed 3 years ago.
I've been trying to modify the AST using annotation processors. I tried extending Lombok, but that seemed too hard, so I decided to use things from com.sun.source.* and com.sun.tools.javac.* However, I am using java 11, and the document I was learning from, "The Hacker's Guide to Javac" http://scg.unibe.ch/archive/projects/Erni08b.pdf, uses Java 6. The api they used is now internal and my module cannot read it.
In IntelliJ, it gave me a few errors, but I clicked on the suggestions (which said things like "Add --Xxx-xxx to xxx" without paying attention to them. When I tried compiling with Maven, it failed, since the module does not read the internals of jdk.compiler.
These are some of my imports:
import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.Context;
My module-info file contains
requires jdk.compiler;
requires java.compiler;
I got messages like "[ERROR]package com.sun.tools.javac.util is declared in module jdk.compiler, which does not export it to module OtherAnnot" and "[ERROR] (package com.sun.tools.javac.tree is declared in module jdk.compiler, which does not export it to module OtherAnnot)"
Edit: I guess this is a duplicate, but I wanted to know if there was some alternative API for AST transformations in java 9.
With the introduction of Project Jigsaw, the JDK has been modularized, allowing users to create their own modules as well. These modules allows you to export packages of yours, allowing programs that require your module (in their module-info.java) to use the exported packages.
Ideally, you'd be prohibited from using classes that reside in packages that are not exported. However, to not break backwards compatibility, VM flags were introduced that allow you to forcefully export packages (that don't belong to you) to your module.
Given your error message, the respective VM flag to add is:
--add-exports jdk.compiler/com.sun.tools.javac.tree=OtherAnnot
The pattern here is:
--add-exports THEIR_MODULE/THEIR_PACKAGE=YOUR_MODULE
If the compiler complains that packages aren't exported to the unnamed module, then you can use the following:
--add-exports THEIR_MODULE/THEIR_PACKAGE=ALL-UNNAMED

How to suppress the "requires transitive directive for an automatic module" warning properly?

After upgrading a Maven project to Java 9 and adding a module descriptor, javac complains about a transitive dependency for an automatic module:
[WARNING] /.../src/main/java/module-info.java:[3,35] requires transitive directive for an automatic module
An example module-info.java to reproduce the problem:
module com.example.mymodule {
exports com.example.mymodule.myexportedpackage;
requires transitive com.google.common;
}
The meaning of this warning is completely clear, here are some related links:
What's the difference between requires and requires transitive statements in Java 9?
Why does javac complain about named automatic-modules?
Related OpenJDK issue
The question is — how to suppress this warning, without fixing the actual issue, and without disabling all the other javac warnings?
I've tried the following options, but none of them worked:
#SuppressWarnings("module") in module-info.java
#SuppressWarnings("all") in module-info.java
-Xlint:all,-module command line option
Unfortunately, I cannot fix the actual issue (for now) because "my" module has return types and annotations from third-party (automatic) modules (e.g. Guava). Thus, if I'd use "requires com.google.common" (without transitive), then there would be a different warning, e.g.:
[WARNING] .../MyClass.java:[25,20] class com.google.common.collect.Table in module com.google.common is not indirectly exported using requires transitive
And of course I cannot define module descriptors for the third-party libraries (which are automatic modules right now).
I'm using -Werror which I'd prefer to keep, so the warning isn't merely annoying...
P.S. I do not intend to publish my artifacts to any public repositories.
You could try out the option of switching off the warning using
-Xlint:-requires-transitive-automatic
The changes for which were merged with JDK-8178011 stating:-
There should be two new warnings:
when a named module "requires transitive" an automatic module (default on)
when a named module "requires" an automatic module (default off)
Inferring this from the changes made here and also from the edit to the JEP 261: Module System which confirms that(emphasis mine):-
In both of the modular modes the compiler will, by default, generate
various warnings related to the module system; these may be disabled
via the option -Xlint:-module.
More precise control of these warnings
is available via the exports, opens, requires-automatic, and
requires-transitive-automatic keys for the -Xlint option.
You can also just use #SuppressWarnings like so:
#SuppressWarnings({ "requires-automatic", "requires-transitive-automatic" })
module foo {
// ...
}
The JDK itself uses this technique.
Sadly, the accepted answer didn't help me.
BTW, I am using Java 14 with a bunch of module system hacks for JUnit.
I had to add another flag, so the complete list looks as following:
-Xlint:-exports -Xlint:-requires-transitive-automatic -Xlint:-requires-automatic
I have searched for the error message and found the source code. There, one can see that the corresponding compiler key is called compiler.warn.leaks.not.accessible.not.required.transitive, with the command line arg -Xlint:exports.

How to add a jar to the boot classpath in java 9

In my application that runs on java 8, I am using -bootclasspath:p to add a jar to the boot classpath. In java 9, the option is removed. What is the alternative to do the same in java 9?
You may use -Xbootclasspath/a. Please refer to the release notes which states:-
The boot class path has been mostly removed in this release. The java
-Xbootclasspath and -Xbootclasspath/p options have been removed.
The javac -bootclaspath option can only be used when compiling to JDK 8 or
older. The system property sun.boot.class.path has been removed.
Deployments that rely on overriding platform classes for testing
purposes with -Xbootclasspath/p will need to changed to use the
--patch-module option that is documented in JEP 261.
The -Xbootclasspath/a option is unchanged.
-bootclasspath:p add classes from jar to the begin of default bootstrap class path (prepended). It isn't longer supported in JVM 9 or greater.
-bootclasspath:a add classes from jar to the end of default bootstrap class path (appended). This option is supported in JVM 9 or greater.
https://docs.oracle.com/cd/E15289_01/JRCLR/optionx.htm#i1021218
In my case when I declare variables in this order:
JAVA_OPTS="$SOME_OPT"
JAVA_OPTS="-javaagent:../agent.jar -Xbootclasspath/a:../agent-boot.jar $JAVA_OPTS"
I catch classNotFoundException. And when I reverse order:
JAVA_OPTS="-javaagent:../agent.jar -Xbootclasspath/a:../agent-boot.jar $JAVA_OPTS"
JAVA_OPTS="$SOME_OPT"
ClassNotFound exception disappear.

Downgrading from Java 7 to Java 6

For whatever reason I had to change pc's as a result of the change I now have to use Java 6 (the final update) Instead of java 7. When importing my existing project to Java 6 I get the following error in my auto generated code that was generated by Netbeans and is not modifiable
cannot find symbol
symbol: variable Type
location: class Window
frame.setType(java.awt.Window.Type.POPUP); //Type is underlined
The output for the error is as follows:
javac: invalid target release: 1.7
Usage: javac <options> <source files>
use -help for a list of possible options
C:\Users\Adminstrator\Downloads\NetBeansProjects\NetBeansProjects\Pat0.3\nbproject\build-impl.xml:915: The following error occurred while executing this line:
C:\Users\Adminstrator\Downloads\NetBeansProjects\NetBeansProjects\Pat0.3\nbproject\build-impl.xml:268: Compile failed; see the compiler error output for details.
What does this do? Is it necessary, would deleting that the component help? Which component is it, is there a quick fix?
Your build.xml specifies the target="1.7" flag to javac, which java 6 doesn't know how to interpret. Changing it to 1.6 will technically get past that error.
However, the enum Window.Type was added in Java 7, so you simply can't expect changing the target to work; your project's source uses Java 7 features. I'm sure that's not the only one.
Your options are therefore to methodically go through and remove/replace all Java 7 code (likely introducing some bugs) or just to.. install Java 7.
There is somewhere in your project a setting for the java compiler that tells it to generate classes for jre7. javac from jdk6 cannot generate classes for that version, hence the error. So you should look into the properties of your project and set up javac to generate classes for jr6. You might also have fix some of your non-generated code if for example you have used features that came with java 7 such as diamond operator or multy catch block etc.
Also the javadoc for Window.Type states it is available only since 1.7. You might want to re-generate that code or better yet just install jdk7.

Categories