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;
Related
I am referencing PlayerUtil.getMovementSpeed(player); in my Speed class, and in my PlayerUtil class, I have the method defined as:
public static double getMovementSpeed(Player player) {
//my code here
}
But whenever the getMovementSpeed method is referenced in my other classes, it throws this error:
java.lang.NoSuchMethodError: net.Swedz.util.PlayerUtil.getMovementSpeed(Lorg/bukkit/entity/Player;)D
I thought it may be that Eclipse was exporting incorrectly, but I rebooted it and tried again with no avail.
EDIT: I did try decompiling the exported jar, and the public static double getMovementSpeed(Player player) method does exist in the exported jar.
EDIT: My friend is also having a similar issue, and is using IntelliJ, so Eclipse is not the issue.
EDIT: Class definition for PlayerUtil:
package net.Swedz.util;
public class PlayerUtil implements Listener {
//getMovementSpeed is defined in here
}
Class definition for Speed:
package net.Swedz.hack.detect.move;
public class Speed implements Hack, Listener {
//my detection methods and method containing PlayerUtil.getMovementSpeed(player);
}
SOLUTION: I found on my own that I had classes conflicting between two plugins on my server. I had one jar with net.Swedz.util.PlayerUtil and another with net.Swedz.util.PlayerUtil both with different contents. I added my project name in all lower case after the net.Swedz and it seems to have fixed it!
Thanks!
This is a very simple to troubleshoot.
you have used that method and you were able to compile that class which uses this method.
so that means at compile time it reefers the class PlayerUtil which has this method.
But runtime class loader has loaded the class PlayerUtil which doesn't contain this method.
now what you have to do is just find out where that class has been loaded from (at run time)
if you can recreate the problem while it is running using eclipse/IDEA follow these steps.
(if it runs in in application server or standalone application, then start the application server or application with debug enabled.and you can do remote debug from your IDE).
put a break-point where exception was thrown (where you call this method).
start to debug , it will hit the break-point.
then evaluate this expression PlayerUtil.class.getResource("PlayerUtil.class")
4.you can find the path where the class was loaded from.
now you have two options , decompile the class and check whether that method is these (same return type, same name , same args).
or in debug , you can evaluate PlayerUtil.class.getDeclaredMethods() to find out.
So you can solve the problem by rectifying the class path entries if it was loaded from a wrong place.
I am trying to make a Java app that can load plugins implementing an abstract class and am having an AbstractMethodError with the instances generated from ServiceLoader. The code is a bit heavy so I've made a simplification below.
First, I have an abstract class:
package stuff.TheAbstractClass;
public abstract class TheAbstractClass implements ClassInterface{
//Stuff happens
}
Which implements the below interface:
package stuff.ClassInterface;
public interface ClassInterface {
public String getClassName();
}
I have a service provider NotAbstractClass which extends TheAbstractClass and states so in a meta-inf/services folder:
package anotherstuff.NotAbstractClass;
public final class NotAbstractClass extends TheAbstractClass implements ClassInterface{
private String name = "Silent Bob";
#Override
public String getClassName() { return name; }
}
Then on the main application (which is actually a plugin inside another application), I want to find all classes which extend TheAbstractClass:
package stuff.TheApp;
import java.util.ServiceLoader;
public class TheApp {
private String name;
public final static TheApp INSTANCE = new TheApp();
private TheApp() {
ServiceLoader<TheAbstractClass> serviceLoader =
ServiceLoader.load(TheAbstractClass.class);
for (TheAbstractClass class: serviceLoader) {
name = class.getClassName;
}
}
My application does find NotAbstractClass. I know this since, in the for loop, I can do class.getName() and it'll give me anotherstuff.NotAbstractClass) but gives the error:
java.lang.AbstractMethodError: stuff.TheAbstractClass.getClassName()Ljava/lang/String;
I'm stumped. Any suggestion? Thank you, Pedro
According to the API for AbstractMethodError you get this:
Thrown when an application tries to call an abstract method. Normally,
this error is caught by the compiler; this error can only occur at run
time if the definition of some class has incompatibly changed since
the currently executing method was last compiled.
Just by looking at your code and your comment I see that this could only have happened at runtime.
If that is the case then:
some class has incompatibly changed since the currently executing
method was last compiled
I've tested your logic after some adjustments in a Java compatible form and I had no problems. The only thing that seems to be happening is a change in any of the subclasses of TheAbstractClass.
Another thing I did was to declare the dependencies using the dependency files in: resources/META-INF/services:
file: <full-package>.TheAbstractClass
content: <full-package>.NotAbstractClass
After this I had no problems.
It seems the issue wasn't in the code, but in the IDE (IntelliJ). I deleted all previously packaged jars and made new jars without changing anything and it magically worked... So it's an IDE bug, and not a language issue!
Thanks to #Joao and #hotzst for taking time to read however.
Best, Pedro
My problem is that when class B tries to use A.check() my execution stops due to a java.lang.NoClassDefFoundError.
So here is my class configuration. NB: the classes are in the same packages and I have already checked that the A.class file is placed where it should be.
public class A{
// vars
// declare some public method
public synchronized static boolean check(){
//do stuff, log some info and return boolean
}
}
public class B implements Runnable{
public void run() {
A.check();
}
}
And here is my stacktrace:
java.lang.NoClassDefFoundError:
org/mypackage/A
at org/mypackage.B.run()
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException:
org/mypackage.B
at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:50)
The project is really big and class A is used lots of times before this call without any problem, so i don't think that is something relative to the classpath. Note that this is part of the last call of the software that should close up everything.
Moreover, I have two maven goals: the first one execute the questioned code without any problem, instead the second rise this error every time.
So I have solved my problem and I post here the solution so maybe can be useful for someone else.
First of all the error: java.lang.NoClassDefFoundError
This error is really different from ClassNotFoundException and this is where I'have lost a lot of time.
NoClassDefFoundError in Java is raised when JVM is not able to locate a particular class at runtime which was available at compile time. For example, if we have a method call from a class accessing any member of a Class and that class is not available during runtime then JVM will throw NoClassDefFoundError. It’s important to understand that this is different than ClassNotFoundException which comes while trying to load a class at run-time only and the name was provided during runtime, not on compile time. Many Java developer mingles this two Error and gets confused. Here I quote a really useful blog that I uesd.
So in a shorter way NoClassDefFoundError comes if a class was present during compile time but not available in java classpath during runtime.
But even with those information the problem was still there until I found the mystery: one of the reason that can place the class in a state that can be compiled but not located at runtime is that if you have static initialization that fail (e.g. in my class I had as field a static variable instantiated badly).
So remember to check for you initialization phase if you have static variables in your class this could be the reason of your java.lang.NoClassDefFoundError.
By the way I don't get why this kind of error is not raising some more meaninful errors for example java.lang.ExceptionInInitializerError or something like that.
Try to debug maven execution by running: mvn -X <your_goals>
It would be useful to see your POM file.
If you are working with spring mvc and if you made bean entry in dispatche-servlet.xml for Controller class.
Example :
<bean id="MyClass" class="com.aaps.myfolder.MyClass">
<property name="methodNameResolver">
<ref bean="methodNameResolver" />
</property>
</bean>
And if MyClass.java is not compiled & if no class file is generated in classes folder of your project folder then it wil show java.lang.NoClassDefFoundError.
So check whether the MyClass.class is created or not in classes folder if you are working with spring mvc.
Does Class A have anything that is done in a static block. You can get this exception even if a class is being loaded and static blocks fails for any reason reason. try to put in logging to see if something like this is happening.
After I debugged the code and watched how the object Questionario is made I can see that there is no property punteggioMassimo, even if it is declared on the class.
//QuestionarioBase.java
public class QuestionarioBase extends com.xxx.cms.classgenerator.BaseBean implements Serializable {
//some other properties
protected Integer punteggioMassimo;
//some other getter and setter
public Integer getPunteggioMassimo() {
return punteggioMassimo;
}
public void setPunteggioMassimo(Integer punteggioMassimo) {
this.punteggioMassimo = punteggioMassimo;
}
This class is extended by Questionario.java which has nothing in it.
public class Questionario extends QuestionarioBase implements Serializable {
}
When the object is created in the controller it initializes all the properties besides punteggioMassimo. I also tried to force the initialization using the setPunteggioMassimo in the Expression tab of eclipse, but I had no luck with it!
Here is a picture of the Expression tab:
When the object is created in the controller it initializes all the properties besides punteggioMassimo.
This means to me that your Ide is not taking into account your changes. If you are in Eclipse, clean projects, clean install maven, maven update project, clean tomcat or whatever application server, and then redeploy from scratch. Now you are sure you have the latest version of your class... If using something else, just try to find out if your class is actually deployed, by opening (unzipping) your war (or jar) and checking if your changes are in there. If not, it means there is something wrong with the build process...
I am running into this problem when trying to recompile a single class inside a package.
Now this class uses global types and some of these global types reference it. So taking it out of the package really isn't an option.
So when I try to compile it with javac alone, I get invalid symbol errors and netbeans shows it is trying to compile things like classespackage.globaltype. Basically it is searching for the global classes inside of the package. Is there anyway to stop it from doing that?
Here is the code:
Global
public class Global {
example.Main main;
public Global(example.Main m) {
main = m;
}
}
example.Main
package example;
public class Main {
public static void main(String[] args) {
Global g = new Global(new Main()); // COMPILE ERROR
}
}
I get invalid symbol errors
You probably meant "Cannot find symbol" errors? This can be caused by anything. Imported class which is not in the compiletime classpath, methods which does not exist, variables which are out of the scope. You really need to post the compilation errors to get more detailed answers.
At least, this much sounds like that you didn't specify the dependencies (the imported classes) in the compiletime classpath using the -cp or -classpath argument.
Is there anyway to stop it from doing that?
By listening to those errors and taking actions accordingly.
Update as per the posted code example: the cause of the problem is that classes in the default package (i.e. classes without a package declaration) are invisible to classes inside a concrete package (i.e. classes with a package declaration). You need to put Global in a package. Then it's visible (importable) to classes inside a package.
If you reference the global types in a class package, you'll have to include them in your classpath. When you do javac, make sure you include the global types class in your classpath (with the -cp option.)