NoClassDefFoundError after changing from java8 to java 10 - java

I have googled and searched the best I could, but I still could not find an solution. Maybe my search queries was not correct or details.
I do know there are a number of API changes from java 8 to 10. The jdk structure for 8 to 10 has also a significant changes.
Problem:
I have the following dependencies:
Project A --> Project B --> Project C
Some class in project A will call classes in Project B and B will call C. In Java 8 there were no issues.
After I upgrade to Java 10, a NoClassDefFoundError exception occurs.
I found two ways to overcome the issue
Project A now also depends on Project C
In the Java Build Path tab --> Order and Export tab, checked the Project C checkbox.
Question
Is there a better way to resolve my problem instead of using the solutions I found? Because my project codes are huge and it will take a lot of time to do so.
I would also like to know the underlying cause of the problem if possible.
Code:
ClassA.java (Project A):
package pkg;
public class ClassA {
public ClassA() {
new ClassB();
}
public static void main(String[] args) {
new ClassA();
}
}
ClassB.java (Project B)
package pkg;
public class ClassB {
public ClassB() {
callClassC();
}
public void callClassC() {
ClassC classC = new ClassC();
String info = classC.getInfo();
System.out.println(info);
}
}
ClassC.java (Project C)
package pkg;
public class ClassC {
public String getInfo() {
return "Class c info";
}
}
I also exported a eclipse workspace for my issue. I created this workspace using an older version of eclipse and java.

I can reproduce this. The code compiles, but you get an error when executing.
This is an eclipse bug.
Please report it at https://bugs.eclipse.org.
A possible workaround: Edit the run configuration, go to the Dependencies tab, use Add variable string with the value ${project_classpath}

Related

Write Unit Test In Different Package Calling Private/Protected Methods Using Intellij

I realize this question has been asked before here -> How to create a test directory in Intellij 13?
However, the answer is not working for me and I can't figure out why...
Intellij Version:
IntelliJ IDEA 2016.1.4
Build #IC-145.2070, built on August 2, 2016
JRE: 1.8.0_77-b03 x86
JVM: Java HotSpot(TM) Server VM by Oracle Corporation
MyApp.java
package main.java.com.simpleproject;
public class MyApp {
private int updNum;
public MyApp(int givenNum){
this.updNum = givenNum;
}
private void updateNumPlusTwo(){
this.updNum += 2;
}
protected int getUpdatedNum(){
return this.updNum;
}
}
MyAppTest.java
package test.java.com.simpleproject;
import main.java.com.simpleproject.MyApp;
public class MyAppTest {
public static void main(String[] args) {
MyApp app = new MyApp(4);
app.getUpdatedNum();
app.updateNumPlusTwo();
}
}
The package/directory tree:
The Issue:
What I have tried:
Anyone have any idea how to get this to work?
Your sources directories and packages are wrong.
You have chosen the Maven default sources directories structure of src/main/java for production code, and src/test/java for test code. You should declare both directories as source folders in IntelliJ (Project Structure -> Modules -> select the folders and click on Sources for src/main/java and Tests for src/test/java)
Your packages should be the same: com.simpleproject. The problem is that you have declared 2 different packages (main.java.com.simpleproject and test.java.com.simpleproject) that's why you cannot call a protected method.
It is not possible to call a private method, from the same or different package. You have to use reflection for that. But preferably you should at least put your method protected or package default.
Your test should use JUnit, not a main method. Something like :
package com.simpleproject;
import static org.assertj.core.api.Assertions.assertThat;
public class Test {
#Test
public void shouldTestMyClass() {
// Given
int givenNum = 3;
// When
MyApp myApp = new MyApp(givenNum);
myApp.updateNumPlusTwo();
// Then (use AssertJ library for example)
assertThat(myApp.getUpdatedNum()).isEqualTo(5);
}
}

Java compiler can not find symbol - public class in same package

I've got a problem with a Main class not finding another class being public, in the same folder and the same package. Both classes are named as their files. Here is the part seeming to contain the problem:
The Interface:
package hanoi;
public interface Stack<E> {
...
}
The Over-Class:
package hanoi;
public class DefaultStack<E> implements Stack<E> {
...
}
The Used class:
package hanoi;
public class HanoiStack extends DefaultStack<HanoiDisk> {
public HanoiStack (int a){
for (int b = a; b > 0; b--){
HanoiDisk disk = new HanoiDisk(b);
this.push(disk);
}
}
...
}
Main Class:
package hanoi;
public class TowersOfHanoi{
HanoiStack stack1 = new HanoiStack(0);
HanoiStack stack2 = new HanoiStack(0);
HanoiStack stack3 = new HanoiStack(0);
...
}
File Directory (of both):
...\eclipse\Hanoi2\src\hanoi
Eclipse error: Main class could either not be found or not be loaded
(there is actually a main method in the main class, but the rest of the code gets very complicated and doesnt seem to be interesting right now)
Java Compiler error: could nor find symbol: class HanoiStack
Another hint: a friend of mine is working on the same project, seeming toi have declared the interesting part same as me but not having any issues.
Update: download link to the full program is here
Looks like either Eclipse playing up, or it cant compile the classes for some reason.
1) Clean the project in Eclipse. (Project -> Clean -> Clean all projects) Then restart Eclipse for good measure.
2) Check the folder where the project is configured to build is writable. To check what this is, view the project build path (right click -> Build Path -> Configure build path) under source tab check the output folder.
If neither of these help, could you provide more info where the main class is. E.g. is it in the TowersOfHanoi class?

"constructor has private access" error message

I'm working in Java and have come across an incredibly odd error. I have a very basic class as follows:
public class ClassA{
private static Logger log = Logger.getLogger(ClassA.class.getName());
private boolean trace;
public ClassA(){
trace = log.isTraceEnabled();
}
public void doSomething(){
//does stuff
}
}
I can use this class just fine within my current project. However, when I build, package, and install to my local repo (using Maven, no remote artifact repo set up), other projects cannot properly use this class because they cannot instantiate it. When I try anything like:
ClassA classA = new ClassA();
I get the following compilation error:
ClassA() has private access in [package].ClassA
I've decompiled the .jar in my local repo to ensure the constructor is present and is public - it is. I've also used the -U flag to force updates and the compilation continues to fail. What could be causing this error?
Maybe you have some other ClassA.class file somewhere in the classpath. Check all the jars used by the project that cannot call the constructor: one of them should contain an old version of your class.
My only thought is that you have a problem with your package. Make sure to define the package at the top of the source file for classA using the package keyword. When you call it ensure that the file is in include list with the include keyword. You could be running into the error because ClassA exists in some default package and that is what you are actually calling instead of calling your locally made ClassA class. The code you posted looks fine and you have already double checked to ensure the changes have taken effect in your repository.
//for those with Kotlin-Java mixed projects:
If the said file (With constructor) is in Kotlin and is being used in Java:
Instead of A a = new A(); //which causes the said error
Use A.INSTANCE. …
I have this error, where write "private", instead "public" for class constructor;

Java: Forward declarations of classes in namespaces

How do I do forward declarations in Java?
I have two classes, each needs to call a method in the other and they both reside within different namespaces. For example...
package one;
class A {
public void foo() {
B b = new B();
b.bah();
}
}
and
package two;
class B {
public void bah() {
A a = new A();
a.foo();
}
}
UPDATE
In Eclipse when this code is encountered a compile time error would be thrown up "A cycle was detected in the build path...".
Just import them. Java is a lot cleverer than C++ about these things.
In Eclipse when this code is encountered a compile time error would be thrown up "A cycle was detected in the build path...".
I think that Eclipse is complaining because you have a circular dependency between classes in different Eclipse projects in your workspace. Eclipse wants to be able to build projects in a linear sequence.
If you put the mutually dependent classes into the same project, Eclipse would be happy.
Well, you import the classes:
package one;
import two.B;
class A {
public void foo() {
new B().bah();
}
}
or use their full name:
package one;
class A {
public void foo() {
new two.B().bah();
}
}
But, needless to say, that will cause an exception to be thrown (at least, in the snippet you posted...).
Given the comments here (ie you don't need to do explicit forward declarations as the compiler can cope) I have downgraded the Eclipse error to a warning and will have to just ignore it.
To do this go to...
Window > Preferences > Java > Compiler > Building > Build path problems > Circular dependences

The type Collection is not generic; it cannot be parameterized with arguments <? extends E>

I have a strange problem with Eclipse Galileo.
I set Java 1.6 as my JRE. On this line of code
List templates = new ArrayList ();
I see the following error in Eclipse's problem list:
The type Collection is not generic; it cannot be parameterized with arguments
I don't have any problems with building this project with Ant.
How can I fix it? Looks like it is an Eclipse problem, but because of this error, I can't compile/publish my project from the IDE.
What List are you importing? (see this thread from 2006)
java.awt.List or java.util.List?
Because, as eclipse aptly comments, java.awt.List is not parameterized ;)
Check also the
Java Build path: it must not contain a reference to the J2SE 1.4.2 libraries.
Source Compatibility: project properties -> Java Compiler Settings, Source Compatibility 5.0 or 6.0.
Other than that, there was lots of issue back in 2005 when the latest Eclipse 3.1 beta was supporting J2SE5, but this was fixed since then.
Try tyo use the latest JDK6 in your project.
It's late but still replying, might be helpful for others who are still facing the issue.
I was getting exactly the same issue. The List was proper with util.List. The solution was to order the exports of the libraries.
If you are using Maven or any other Libraries :
In Project -> Build Path -> Configure Build Path -> Order & Exports
Check 'JRE System Libraries' should be above 'Maven Dependencies'
This worked for me.
For those, who will get there from Google: the problem was with cryptix library. When I removed it from java build path the project is compiled sucesfully.
Did you name your class list? i.e:
import java.util.*;
public class List { // can't do this, name this something else.
public static void main(String[] args) {
List<Integer> l = new ArrayList<Integer>();
}
}
Hey, I removed the cryptic library and it didn't work. But then I put JRE System Library at the top, and it worked. Really weird.
Sometimes it's an eclipse hiccup and eclipse -clean plus refreshing all projects helps.
Edit
Does it change anything when you replace your code with:
java.util.List templates = new java.util.ArrayList();
or even
java.util.List<Object> templates = new java.util.ArrayList<Object>();
?
put the entry "JRE System Library..." at the top in project, properties, java build path, order and export
use "import java.util.List"
instead of default import "import antlr.collections.List;"
and use the JRE5 or above for generic support of collection API....
for example:
public class AClass<T extends Object>
{
public HashMap<String, String> myMap;
}
if I write:
public class BClass
{
private AClass aClass = new AClass();
public void test()
{
aClass.get("test");
//return Object class
}
}
but if I write:
public class BClass
{
private AClass<?,?> aClass = new AClass<?,?>();
public void test()
{
aClass.get("test");
//return String class
}
}
I changed the import
import javax.swing.text.html.HTMLDocument.Iterator;
to
import java.util.Iterator;
then it worked for me
Some ideas:
check the JRE library being used in your project (check the package explorer).
check the installed JREs in the eclipse settings (same as used by ant).
comment out the line just to check if it really is the error cause.
retype the whole line from scratch.
install a new (clean) version of eclipse, in a new folder (testing).
make java buildpath reference to greater than or equal to java 1.5
or you try to add the "import java.util.List" statement then you can see that
eclipse is saying it is conflicting with some other List type
for example it may be conflicting with com.lowagie.xx.xxx.List etc try to avoid these import
statements
Try to remove import antlr.collections.List; and click Ctr+space to use java.util

Categories