I have an issue where NoClasDefFoundError is being thrown. It puzzles me since I am using interfaces, and no class definition should be available. I have read through some posts which point to Classpath, but I don't believe that to be the issue here (although I may be wrong). I am using NetBeans 6.9.1 IDE.
I have created a sample setup to reproduce the issue. Four projects: Interfaces, Objects, Locator and Consumer. Below you will find the implementations.
At runtime consumer coplains about missing SomeObject implementation, which it should not be aware of since it is accepting interface.
Exception in thread "main"
java.lang.NoClassDefFoundError:
objects/SomeObject
What am I missing?
package interfaces;
public interface ISomeInterface { }
package objects;
import interfaces.ISomeInterface;
public class SomeObject implements ISomeInterface{ }
package locator;
import interfaces.ISomeInterface;
import objects.SomeObject;
public class Locator { public static ISomeInterface LocateImplementation() { return new SomeObject(); }}
package consumer;
import interfaces.ISomeInterface;
import locator.Locator;
public class Main { public static void main(String[] args) { ISomeInterface object = Locator.LocateImplementation(); }}
You can get a NoClassDefFoundError exception with interfaces just as you can with classes. Consider the "Class" in the name of the exception to be the .class file that is generated from compiling a class or interface, not a Java class.
This is saying that the class/interface objects.SomeObject isn't visible on your classpath. Check the location of that .class file and ensure that it's on your classpath - if you're positive it's there, give us some screen shots or something that might help to debug the problem.
Think of NoClassDefFoundError as a runtime linkage problem. JRE loaded one class (or an interface) and it references another class (or an interface), but that referenced class isn't found.
The only way this can happen if you have packaging/classpath issues such that your runtime environment doesn't reflect how things are at build time.
If you are launching this from IDE, make sure that you aren't ignoring any errors and launching anyway. Some classes will not be generated that way.
Usually I run into these problems not when a class is missing, but when there is an error in the static initializers.
Try running your code in a debugger, and set the exception breakpoint to break when any exception is thrown, whether caught or not. I bet you have an uncaught exception in the static initializer for some reason.
In the locateImplementation() method you are returning "new SomeObject()",
JVM needs to have its definition when called. I think it is missing.
You should check if your SomeObject class is in class path because -
Well the JVM will be running the below code -
ISomeInterface object = Locator.LocateImplementation();
and when it does that it will call Locator.LocateImplementation(). This code internally tries to instantiate your SomeObject class which it does not find in the classpath.
So your below understanding
It puzzles me since I am using
interfaces, and no class definition
should be available.
Is not really valid.
Any Interface must be declared inside class
public class Calbacks {
public interface IBaseFragmentInterface {
void NotifyMainActivity();
}
}
Related
I have a Java class that has a private constructor:
public class MyClass {
private static final MyClass myClass = new MyClass();
private MyClass() {}
public static MyClass getInstance() {
return myClass;
}
}
This class is being used in the application like this:
MyClass myClass = MyClass.getInstance();
The whole application is also exported as a JAR and used in another application.
When I try to do the same in another application (Where its being invoked from a JAR) I get the following error:
java.lang.NoClassDefFoundError: Could not initialize class com.example.MyClass
I am not sure if this is the required behavior for a class with a private constructor, or is there something else wrong with it?
Thanks!
Your error has nothing to do with static-ness or your constructor. From the javadocs:
Thrown if the Java Virtual Machine or a ClassLoader instance tries to
load in the definition of a class (as part of a normal method call or
as part of creating a new instance using the new expression) and no
definition of the class could be found. The searched-for class
definition existed when the currently executing class was compiled,
but the definition can no longer be found.
NoClassDefFoundError means the class definition is unavailable when you're trying to run your program. This is some kind of path error - either this class is not in the exported jar or it's not being included on the classpath when it's being run.
Are you sure you have correct included the JAR in the classpath of the second application?
NoClassDefFoundError Occurs when JVM tries to load a particular class that is the part of your code execution (as part of a normal method call or as part of creating an instance using the new keyword) and that class is not present in your classpath but was present at compile time because in order to execute your program you need to compile it and if you are trying use a class which is not present compiler will raise compilation error.
I have created a class with the same name and package as the String java class.
package java.lang;
public class String {
public String() {
System.out.println("This is my string ");
}
public void show() {
System.out.println("From show mathod .");
}
}
When I try to invoke this show method it gives error for no such method. It refers to API class. why.?
import java.lang.*;
public class Test {
public static void main(String[] args) {
String str = new String();
str.show();
}
}
I know that I am violating the rule of unique package and class name. But I want to know if I add two jars in my class-path and they have same structure. In such case is there any behaviour defined by Java which class will be loaded.
And why java does not load my class instead of Java API classes? (I also tried this with other api defined classes)
#Please do not give answer like I am violating the rule or work arounds.
Java comes shipped with classes. One of these classes is java.lang.String.
These pre-shipped classes take precedence in the classpath over any class that you might write that have the same package and name.
Whenever you do a new java.lang.String(), regardless if you have a class with the same package and name, the runtime class shipped by Oracle will take precedence.
Since java.lang.String is also a final class, there's no way you will be able to add new methods to it. The best solution is for you to create a new class in a different package or under a different name.
classes can not be redefined after the VM has started and the class has been loaded. As java.lang.String is being used way before your code, it would already be loaded.
I am not sure that you could even achieve this using a byte code enhancement library like javassist
Just tried to write custom ClassLoader to load my class named java.lang.String. Ran out of luck here:
Exception in thread "main" java.lang.SecurityException: Prohibited package name: java.lang
at java.lang.ClassLoader.preDefineClass(ClassLoader.java:658)
at java.lang.ClassLoader.defineClass(ClassLoader.java:794)
at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
at temp.TempLoader.findClass(TempLoader.java:20)
at temp.TempLoader.main(TempLoader.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Offending code in JRE java.lang.ClassLoader:
if ((name != null) && name.startsWith("java.")) {
throw new SecurityException
("Prohibited package name: " +
name.substring(0, name.lastIndexOf('.')));
}
It would be interesting to see any "pure Java" solution (not involving out-of-JVM changes to runtime) which can workaround this.
You may wonder how JVM itself loads java.* classes? Well, they loaded by so called bootstrap loader, during initialization of JVM instance. I assume, there's no public API to that classloader.
I don't know what you are trying to do exactly, but I can suggest a different approach.
In java String class is final, so, it can't be extended. Create a wrapper class which has your additional methods and a String field.. Now you can define and call show() on your class (You can't do it on the String directly..) If split() is called on your class, then just delegate the call to String class's split().
expose a method getInstance() in your wrapper . Whenever myWrapper.getInstance() is called, call new String() from there..
In my main I have the following statement
Class booki = Class.forName("Book");
which throws a java.lang.ClassNotFoundException exception
when I use the full path like Class booki = Class.forName("javatests.Book"); it is ok.
The main class and the Book class are in the same package, I also tried using import static javatests.Book.*; but still it throws the exception if I don't set the full path javatests.Book. Can someone explain to me why?
Class.forName resolves a fully qualified class name to the class. Since a method does not know where it is called from neither the package of the calling class nor imports in the calling class play any role.
From docs Class#forName
public static Class<?> forName(String className)
throws ClassNotFoundException
Parameters:
className - the fully qualified name of the desired class.
So this will not throw ClassNotFoundException
Class booki = Class.forName("javatests.Book");
For example, it is not needed to import java.lang.* package in java program but to load class Thread from java.lang package you need to write
Class t = Class.forName("java.lang.Thread");
the above code fragment returns the runtime Class descriptor for the class named java.lang.Thread
You always need a qualified class name unless it's inside the same package. If i define a class foo in my package i can call a method Class testClass = Class.forName("foo") , but i can't call Class testClass = Class.forName("SecureRandom"); even if I import SecureRandom. That's just how the function works. It probably has a shortcut where it tries to find things inside local packages, but doesn't do much behind that.
Firstly the Book class must be in the package javatests.
the JVM load the class by name,through the classpath.
There is no class named "Book" in the classpath.
So JVM give you a ClassNotFoundException when excuse Class.forName("Book").
But 'Class.forName("javatests.Book")' tells JVM the class named 'Book' is in package 'javatests'.
So the JVM can find it and load it.
I hope my answer is helpful :)
JLS provides the following description:
Class lookup is always on behalf of a referencing class and is done through an instance of ClassLoader. Given the fully qualified name of a class, this method attempts to locate, load, and link the class.
The JDK uses one instance of ClassLoader that searches the set of directory tree roots specified by the CLASSPATH environment variable; and obviously it is not aware of the place (package) it has been called. That is why it needs fully qualified name.
I am getting an exception and I can't find the reason of it.
The exception I get is :
java.lang.IllegalAccessError: tried to access method Connected.getData(Ljava/lang/String;)Ljava/sql/ResultSet; from class B
The method is public.
public class B
{
public void myMethod()
{
Connected conn = new Connected(); // create a connected class in order to connect to The DB
ResultSet rs = null; // create a result set to get the query result
rs = conn.getData(sql); // do sql query
}
}
public class Connected
{
public ResultSet getData(String sql)
{
ResultSet rs = null;
try
{
prepareConnection();
stmt = conn.createStatement();
stmt.execute(sql);
rs = stmt.getResultSet();
}
catch (SQLException E)
{
System.out.println("Content.getData Error");
E.printStackTrace();
}
return rs;
}
i am using apache tomcat 5.5.12
and JAVA 1.6
This happens when accessing a package scoped method of a class that is in the same package but is in a different jar and classloader.
This was my source, but the link is now broken. Following is full text from google cache:
Packages (as in package access) are scoped per ClassLoader.
You state that the parent ClassLoader loads the interface and the child
ClassLoader loads the implementation. This won't work because of the
ClassLoader-specific nature of package scoping. The interface isn't visible to
the implementation class because, even though it's the same package name,
they're in different ClassLoaders.
I only skimmed the posts in this thread, but I think you've already discovered
that this will work if you declare the interface to be public. It would also
work to have both interface and implementation loaded by the same ClassLoader.
Really, if you expect arbitrary folks to implement the interface (which you
apparently do if the implementation is being loaded by a different
ClassLoader), then you should make the interface public.
The ClassLoader-scoping of package scope (which applies to accessing package
methods, variables, etc.) is similar to the general ClassLoader-scoping of
class names. For example, I can define two classes, both named com.foo.Bar,
with entirely different implementation code if I define them in separate
ClassLoaders.
Joel
You are almost certainly using a different version of the class at runtime to the one you expect. In particular, the runtime class would be different to the one you've compiled against (else this would have caused a compile-time error) - has that method ever been private? Do you have old versions of the classes/jars on your system anywhere?
As the javadocs for IllegalAccessError state,
Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.
I'd definitely look at your classpath and check whether it holds any surprises.
This happened to me when I had a class in one jar trying to access a private method in a class from another jar. I simply changed the private method to public, recompiled and deployed, and it worked ok afterwards.
I was getting this error on a Spring Boot application where a #RestController ApplicationInfoResource had a nested class ApplicationInfo.
It seems the Spring Boot Dev Tools was using a different class loader.
The exception I was getting
2017-05-01 17:47:39.588 WARN 1516 --- [nio-8080-exec-9]
.m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused
by Handler execution:
org.springframework.web.util.NestedServletException: Handler dispatch
failed; nested exception is java.lang.IllegalAccessError: tried to
access class com.gt.web.rest.ApplicationInfo from class
com.gt.web.rest.ApplicationInfoResource$$EnhancerBySpringCGLIB$$59ce500c
Solution
I moved the nested class ApplicationInfo to a separate .java file and got rid of the problem.
If getData is protected then try making it public. The problem could exist in JAVA 1.6 and be absent in 1.5x
I got this for your problem. Illegal access error
I was getting same error because of configuration issue in intellij.
As shown in screenshot.
Main and test module was pointing to two different JDK. (Press F12 on the intellij project to open module settings)
Also all my dto's were using #lombok.Builder which I changed it to #Data.
From Android perspective:
Method not available in api version
I was getting this Issue primarily because i was using some thing that is not available/deprecated in that Android version
Wrong way:
Notification.Builder nBuilder = new Notification.Builder(mContext);
nBuilder.addAction(new Notification.Action(android.R.drawable.ic_menu_view,"PAUSE",pendingIntent));
Right way:
Notification.Builder nBuilder = new Notification.Builder(mContext);
nBuilder.addAction(android.R.drawable.ic_media_pause,"PAUSE",pendingIntent);
here Notification.Action is not available prior to API 20 and my min version was API 16
Just an addition to the solved answer:
This COULD be a problem with Android Studio's Instant Run feature, for example, if you realized you forgot to add the line of code: finish() to your activity after opening another one, and you already re-opened the activity you shouldn't have reopened (which the finish() solved), then you add finish() and Instant Run occurs, then the app will crash since the logic has been broken.
TL:DR;
This is not necessarily a code problem, just an Instant Run problem
In my case the problem was that a method was defined in some Interface A as default, while its sub-class overrode it as private. Then when the method was called, the java Runtime realized it was calling a private method.
I am still puzzled as to why the compiler didn't complain about the private override..
public interface A {
default void doStuff() {
// doing stuff
}
}
public class B {
private void doStuff() {
// do other stuff instead
}
}
public static final main(String... args) {
A someB = new B();
someB.doStuff();
}
In my case I was getting this error running my app in wildfly with the .ear deployed from eclipse. Because it was deployed from eclipse, the deployment folder did not contain an .ear file, but a folder representing it, and inside of it all the jars that would have been contained in the .ear file; like if the ear was unzipped.
So I had in on jar:
class MySuperClass {
protected void mySuperMethod {}
}
And in another jar:
class MyExtendingClass extends MySuperClass {
class MyChildrenClass {
public void doSomething{
mySuperMethod();
}
}
}
The solution for this was adding a new method to MyExtendingClass:
class MyExtendingClass extends MySuperClass {
class MyChildrenClass {
public void doSomething{
mySuperMethod();
}
}
#Override
protected void mySuperMethod() {
super.mySuperMethod();
}
}
I was getting similar exception but at class level
e.g. Caused by: java.lang.IllegalAccessError: tried to access class ....
I fixed this by making my class public.
I've come across an oddity of the JLS, or a JavaC bug (not sure which). Please read the following and provide an explanation, citing JLS passage or Sun Bug ID, as appropriate.
Suppose I have a contrived project with code in three "modules" -
API - defines the framework API - think Servlet API
Impl - defines the API implementation - think Tomcat Servlet container
App - the application I wrote
Here are the classes in each module:
API - MessagePrinter.java
package api;
public class MessagePrinter {
public void print(String message) {
System.out.println("MESSAGE: " + message);
}
}
API - MessageHolder.java (yes, it references an "impl" class - more on this later)
package api;
import impl.MessagePrinterInternal;
public class MessageHolder {
private final String message;
public MessageHolder(String message) {
this.message = message;
}
public void print(MessagePrinter printer) {
printer.print(message);
}
/**
* NOTE: Package-Private visibility.
*/
void print(MessagePrinterInternal printer) {
printer.print(message);
}
}
Impl - MessagePrinterInternal.java - This class depends on an API class. As the name suggests, it is intended for "internal" use elsewhere in my little framework.
package impl;
import api.MessagePrinter;
/**
* An "internal" class, not meant to be added to your
* application classpath. Think the Tomcat Servlet API implementation classes.
*/
public class MessagePrinterInternal extends MessagePrinter {
public void print(String message) {
System.out.println("INTERNAL: " + message);
}
}
Finally, the sole class in the App module...MyApp.java
import api.MessageHolder;
import api.MessagePrinter;
public class MyApp {
public static void main(String[] args) {
MessageHolder holder = new MessageHolder("Hope this compiles");
holder.print(new MessagePrinter());
}
}
So, now I attempt to compile my little application, MyApp.java. Suppose my API jars are exported via a jar, say api.jar, and being a good citizen I only referencd that jar in my classpath - not the Impl class shiped in impl.jar.
Now, obviously there is a flaw in my framework design in that the API classes shouldn't have any dependency on "internal" implementation classes. However, what came as a surprise is that MyApp.java didn't compile at all.
javac -cp api.jar src\MyApp.java
src\MyApp.java:11: cannot access impl.MessagePrinterInternal class file for impl.MessagePrinterInternal not found
holder.print(new MessagePrinter());
^
1 error
The problem is that the compiler is trying to resolve the version print() to use, due to method overloading. However, the compilation error is somewhat unexpected, as one of the methods is package-private, and therefore not visible to MyApp.
So, is this a javac bug, or some oddity of the JLS?
Compiler: Sun javac 1.6.0_14
There is is nothing wrong with JLS or javac. Of course this doesn't compile, because your class MessageHolder references MessagePrinterInternal which is not on the compile classpath if I understand your explanation right. You have to break this reference into the implementation, for example with an interface in your API.
EDIT 1: For clarification: This has nothing to do with the package-visible method as you seem to think. The problem is that the type MessagePrinterInternal is needed for compilation, but you don't have it on the classpath. You cannot expect javac to compile source code when it doesn't have access to referenced classes.
EDIT 2: I reread the code again and this is what seems to be happening: When MyApp is compiled, it tries to load class MessageHolder. Class MessageHolder references MessagePrinterInternal, so it tries to load that also and fails. I am not sure that is specified in the JLS, it might also depend on the JVM. In my experience with the Sun JVM, you need to have at least all statically referenced classes available when a class is loaded; that includes the types of fields, anything in the method signatures, extended classses and implemented interfaces. You could argue that this is counter-intuitive, but I would respond that in general there is very little you do with a class where such information is missing: you cannot instantiate objects, you cannot use the metadata (the Class object) etc. With that background knowledge, I would say the behavior you see is expected.
First off I would expect the things in the api package to be interfaces rather than classes (based on the name). Once you do this the problem will go away since you cannot have package access in interfaces.
The next thing is that, AFAIK, this is a Java oddity (in that it doesn't do what you would want). If you get rid of the public method and make the package on private you will get the same thing.
Changing everything in the api package to be interfaces will fix your problem and give you a cleaner separation in your code.
I guess you can always argue that javac can be a little bit smarter, but it has to stop somewhere. it's not human, human can always be smarter than a compiler, you can always find examples that make perfect sense for a human but dumbfound a compiler.
I don't know the exact spec on this matter, and I doubt javac authors made any mistake here. but who cares? why not put all dependencies in the classpath, even if some of them are superficial? doing that consistently makes our lives a lot easier.