JPMS Module System Issue - java

I created 2 random modules I exported "com.alice" package from folder A and require the module in folder B. Then compiled A: javac mod10/A/module-info.java mod10/A/com/alice/Ship.java and tried to compile B javac mod10/B/module-info.java mod10/B/com/alice2/Main.java. And I get this:
error: module not found: com.alice
requires com.alice;
^
1 error
why I get "module not found" error message?
Shouldn't it be the whole point of exporting a module to make it visible to other modules?
In mod10/A/module-info.java
module com.alice {
exports com.alice;
}
Ship.java
package com.alice;
public class Ship {
private String name;
public Ship() {
this.name = "Ship Created";
}
public String getName() {
return this.name;
}
}
In mod10/B/module-info.java
module com.alice2 {
requires com.alice;
}
Main.java
package com.alice2;
import com.alice;
public class Main {
public static void main(String[] args) {
Ship x = new Ship();
System.out.println("Ship made" + x.getName());
}
}
Folder Tree:
mod10 (root)
|_ A
|_ com
|_ alice
|_ Ship.java
|_ module-info.java
|_ B
|_ com
|_ alice2
|_ Main.java
|_ module-info.java

Related

Error: package exists in another module: com.company.feature.apimodule in Intellij

I created a small project in Intellij Idea to mimic what I am seeing trying to migrate a large legacy codebase to OPENJDK16. Here is the directory structure:
$ tree
/cygdrive/c/projects/play
|--api
|----api.iml
|----src
|------module-info.java (module com.company.feature.apimodule)
|------com
|--------company
|----------feature
|------------ApiRunnable.java
|--home
|----home.iml
|----src
|------module-info.java (module com.company.feature.homemodule)
|------com
|--------company
|----------feature
|------------Runnable1.java
|--Modules
|----.idea (Idea stuff in here)
|----out
|------production
|--------api
|--------home
module com.company.feature.apimodule
{
exports com.company.feature;
}
package com.company.feature;
public interface ApiRunnable
{
public void play(String[] strings);
}
module com.company.feature.homemodule
{
requires com.company.feature.apimodule; //Error Module not found
// requires apimodule; //Error Module not found
// requires com.company.feature.ApiRunnable; //Error Module not found
}
package com.company.feature;
public class Runnable1 implements ApiRunnable
{
#Override
public void play(String[] strings)
{
int count = 1;
for (String str : strings)
{
System.out.println("String " + count++ + " " + str);
}
}
public static void main(String[] args)
{
Runnable1 myRun = new Runnable1();
myRun.play(args);
}
}
Note the directory structure is identical in api and home. This is intentional as my legacy codebase has this structure. This small example seems to duplicate the problems I am having and I can't figure out if the structure is the problem. It did compile and run fine using the unnamed-module.
Error #1 when doing a rebuild
C:\Projects\play\home\src\com\company\feature\Runnable1.java
java: package exists in another module: com.company.feature.apimodule
Does this mean that I can't have identical package trees in api and home?
Error #2
The homemodule cannot see the apimodule, I keep getting (Module not found) no matter what I put in the requires line.
Is this related to Error #1? If not, how do I fix this without resorting to the unnamed module for everything?
This problem was resolved by putting the module-info.java in the right directory. This is poorly documented and was found by trial and error.
The right directory is api:
module apimodule
{
exports com.company.feature;
}
and home:
module homemodule
{
requires apimodule;
}
It appears that once the module-info.java files are in place, the Runnable1.java doesn't need the import statements, since the imported package is the same as the local one.

"Cannot Find Symbol" even though classes are in the same package [duplicate]

I've the root directory like this :
├── classes
└── src
└── vehicles
├── Bicycle.java
└── BicycleMain.java
Bicycle.java
package vehicles;
public class Bicycle {
public int cadence;
public int gear;
public int speed;
public Bicycle(int startCadence, int startSpeed, int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void setSpeed(int newValue) {
speed = newValue;
}
public int getGear() {
return gear;
}
public int getCadence() {
return cadence;
}
public int getSpeed() {
return speed;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
BicycleMain.java
package vehicles; import vehicles.*;
public class BicycleMain {
public static void main (String args[]){
Bicycle Bike = new Bicycle(10, 20, 1);
System.out.println("We have a new bicycle with speed = " +Bike.getSpeed()+", cadence = "+Bike.getCadence()+", gear = "+Bike.getGear());
} }
I compiled the Bicycle.java and successful, but not for BicycleMain.java :
symbol : class Bicycle
location: class vehicles.BicycleMain
Bicycle Bike = new Bicycle(10, 20, 1);
^
src/vehicles/BicycleMain.java:6: cannot find symbol
symbol : class Bicycle
location: class vehicles.BicycleMain
Bicycle Bike = new Bicycle(10, 20, 1);
^
2 errors
I try to run these files with Netbeans and IT WORKS! but why it doesn't work when I compile in CLI?
First, To compile the java source file using javac you need to specify the files to compile explicitly.
Example:
javac PathToSourceFile/FileName.java
you need not provide the path if the source file is in the current working directory.
Second, whenever java encounters import abc.xyz.ClassName; it tries to resolve abc/xyz/ClassName with respect to the classpath or current working directory.
So if you are inside the vehicles folder and compile your code, it wont compile because it will look for folder vehicles inside folder vehicles (which doesn't exist!).
but, you can do this when inside the vehicles folder
javac -cp ../ BicycleMain.java
and it should compile, because classpath will be set to the directory(../) containing vehicles. which will resolve your Bicycle class.
and then use
java -cp ../ vehicles/BicycleMain to run.
Try deleting the line import vehicles.*; from BicycleMain.java and them compiling with javac in command line.
By the way it happens because while you are compiling in javac you are in the folder vehicles and you write a statement import vehicles.*; in BicycleMain.java which means to the compiler there is another folder vehicles within the vehicles folder which is not the case here
I have solved this problem, compiling from "src".
Something like this: javac ./my_folder/my_file.java
Kind Regards
I tried all the solutions here but eventually I found that the problem for me was I was using different versions of the JDK and JRE.
Check JRE version:
java -version
Check JDK version:
javac -version
Just remove the package line from beginning and it'll work 100%.
Go to the folder in which files are stored via terminal and
type javac *.java
There will be no need to import classes too.

Java loading JAR dynamically: NoClassDefFoundError

Let's say I have a main class App that loads all jars in the sub-directory plugins using a URLClassLoader:
public class App(){
public static void main(String[] args){
for(File f : new File("plugins").listFiles()){
URL[] urls = { new URL("jar:file:" + "plugins/" + f.getName() + ".jar" + "!/") };
URLClassLoader cl = URLClassLoader.newInstance(urls);
Class<?> clazz = cl.loadClass(f.getName().toLowerCase()+"."+f.getName());
cl.close();
Plugin p = ((Plugin) clazz.newInstance());
}
}
}
All those jars contain a class that implements an interface Plugin.
+-- Main.jar
| +-- App.class
| +-- Plugin.class
|
+-- Plugins/
| +-- PluginTest.jar
| +-- plugintest
| +-- PluginTest.class
| +-- Two.class
That's all working fine if I write my code just in the PluginTest class. But as soon as I try to access Two from PluginTest, I'm getting a big error:
Exception in thread "Thread-4" java.lang.NoClassDefFoundError: plugintest/Two
[...]
How should I load the the class correctly? Need help! Thanks.
Do not close your classloader.
Remove cl.close();statement.

Java error Package does not exist

My main folder is ABC inside it is 2 folders named classes and src, inside src is 2 folders named objectFile and testFile, inside objectFile is ABC.java while inside testFile is TestABC.java.(inside classes is the same but .class instead) now ABC contains
package objectFile;
public class ABC
private int something;
while TestABC.java contains
package testFile;
import objectFile.ABC;
public class TestABC
error says TestABC.java:2: error: package objectFile does not exist
import objectFile.ABC;
Are you specifying the sourcepath? This tells the compiler where to find the classes that it needs to import.
javac -sourcepath src -d classes src\testFile\TestABC.java
Note that this compiles not just TestABC.java, but ABC.java as well (because of your import statement).
You can then put the classes into an archive using the jar command:
jar cfe myJavaArchive.jar testFile/TestABC -C classes .
This will create a new jar with the filename myJavaArchive.jar and entrypoint testFile/TestABC made from all the files in the classes directory.
Because it is the entry point, TestABC must have a main method, e.g.
package testFile;
import objectFile.ABC;
public class TestABC {
public static void main(String[] args) {
ABC abc1 = new ABC(1);
ABC abc2 = new ABC(2);
System.out.println("abc1.i is " + abc1.getI());
System.out.println("abc2.i is " + abc2.getI());
}
}
and
package objectFile;
public class ABC {
private int i;
public ABC(int i) {
this.i = i;
}
public int getI() {
return i;
}
}
Then you can execute the code using the java -jar command:
java -jar myJavaArchive.jar

How to create a sample java.lang.SecurityException: sealing violation: package .. is sealed

we've an issue with a long-running Java process suddenly spitting out java.lang.SecurityException: sealing violation: package .. is sealed
after overwriting a sealed jar while the JVM is running.
I kind of understand this exception, but in order to reproduce this (and what follows), I'm trying to artificially create a sealed exception and it's not working.
There's a jar file named 'seal.jar' with a META-INF/MANIFEST.MF file like this:
Manifest-Version: 1.0
Sealed: true
This package contains classes A1, A2, A3 like this:
package sealed;
public class A1
{
public A1()
{
System.err.println("Created version 1.0 of " + this.getClass());
}
}
There's a second jar seal-2.0.jar with the same three classes but printing "version 2.0"
Now a third jar file (run.jar) has this content:
import sealed.A1;
import sealed.A2;
import sealed.A3;
public class SealingTest
{
public static void main(String[] args) {
int cnt=0;
try {
while(true) {
if( cnt%3==0 ) {
new A1();
}
else if( cnt%3==1 ) {
new A2();
}
else if( cnt%3==2 ) {
new A3();
}
Thread.sleep(5000);
cnt++;
}
}
catch (Throwable t) {
t.printStackTrace();
}
}
}
And I thought the this code would then create a sealed exception when I do the following:
C:\CodeStreet\FTP>java -cp run.jar;seal-1.0.jar SealingTest
Created 1.0 of class sealed.A1 # now executing: copy seal-2.0.jar seal-1.0.jar
Created 2.0 of class sealed.A2
Created 2.0 of class sealed.A3
Created 1.0 of class sealed.A1
So it looks like A1 is loaded from seal-1.0.jar, but A2 is loaded from the overwritten seal-1.0.jar.
Shouldn't there be a sealing violation because the first class (A1) is loaded from seal-1.0.jar and the second class (A2) from the overwritten file ?
Please try the following:
remove A3.java from seal-1.0.jar, but keep it in seal-2.0.jar;
have both sealed jars in the classpath and run the test program.
That should give you the desired "SecurityException: sealing violation".

Categories