I have read that Inheritance is a "compile-time' phenomenon. Also in a different place I have read that the superclass code is loaded by classloader, which I deduce happens at run-time. This is causing me some confusion regarding the nature of inheritance. Does the class file of sublass contain the actual compiled code of superclass, or is it accessed at run-time?
So consider you create a class that inherits a class that is included in a 3rd party jar file.
In order to compile your code you need to have the 3rd party jar file in the classpath of your compiler.
In order to run your code you will also need the jar file in the classpath of the java command that launches the application.
Your subclass does not contain the code of the superclass, it is in the jar files. Your compiled class contains a reference to the superclass. When your class is loaded by the classloader it searches the classpath for the superclass and loads it.
Where did you read it's compile time? I guess if you're compiling your subclass then yes, it needs to have a superclass to reference when being compiled.
But when you actually run the code it is dynamically linked as per:
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
"The Java Virtual Machine dynamically loads, links and initializes classes and interfaces"
Related
For a given Java source code file I want to list all the (fully qualified names of) classes that are (directly) required for compilation. In other words: All classes that are directly used by the code in the source code file, coming from imports, fully qualified names in the source code and other compile time means, but not by reflection or other runtime means.
Is there a way to "ask" the java compiler for this list? Are there other ways to get it?
PS: By "directly" I mean the following: If my source code file requires class A for compilation which uses class B, then class B has to be present to compile the code, but it is not a direct use.
You can try this:
It can be eaily done with just javac. Delete your class files and then compile the main class. javac will recursively compile any classes it needs (providing you don't hide package private classes/interfaces in strangely named files).
I plan on becoming a certified Java programmer and am studying from the Sierra-Bates book. I had a question about classpaths. Do classpaths need to find only the supporting classes of the class I'm running/compiling, or the supporting classes and the class itself? Also, when I'm getting classes in packages from classpaths, is it legal to just put the adress of the file(the path to it), instead of putting it's root package. Thanks.
1 - a classpath has to give access to each class that needs to run in your program. That would include the main class and any classes it calls and those they call. If there is some code in one of those classes that is never called, in many cases, you don't need to have the classes referenced by the uncalled code.
2 - you have to put the root of the packages in the classpath. So a class "com.bob.myprog.Main" would need to have the class path point to the folder where the "com" package/folder lies. It will need to contain a "bob" folder and "bob" will need to contain a "myprog" folder with "Main.class" in it.
Classpath has to contain both the supporting classes and the class itself.
However, sometimes you can run a single file without specifying classpath (and it will work).
As specified in http://docs.oracle.com/javase/tutorial/essential/environment/paths.html :
The default value of the class path is ".", meaning that only the
current directory is searched. Specifying either the CLASSPATH
variable or the -cp command line switch overrides this value.
Therefore, if you have a class MyClass compiled in the current directory, the following will work:
java MyClass
while pointing classpath to another directory will lead to an error (classpath no longer contains MyClass):
java -cp lib MyClass
When you have a class in a package, it is not enough to put the address to the class file in the classpath. According to SCJP Sun Certified Programmer for Java 5 Study Guide:
In order to find a class in a package, you have to have a directory in
your classpath that has the package's leftmost entry (the package's
"root") as a subdirectory.
Recently have been touched Java classloaders and suddenly recognized that do not fully understand what happens step-by-step when someone calls
java -jar App.jar
Well I guess
a new instance of JVM is created
it uses ClassLoader to load main class and other classes
byte-code is started to execute from main() method
But still I suppose there are many things I need to know more about it.
Who and how decides which classes should be loaded at startup and which once needed?
I have found two related questions but there it is not explained how to apply that to Java realities.
What happens when a computer program runs?
What happens when you run a program?
•Who and how decides which classes should be loaded at startup and which once needed?
we need to understand the fundamentals of java class loading. Initially bootstrap classloader (it is implemented natively as part of the VM itself) is responsible for loading core system classes. Then there are other class loaders as well like Extension, system, user-defined(optional) class loaders which decide when and how classes should be loaded.
Fundamentals of class loading
The decision is made by the classloader. There are different implementations, some of which pre-load all classes they can and some only loading classes as they are needed.
A class only needs to be loaded when it is accessed from the program code for the first time; this access may be the instantiation of an object from that class or access to one of its static members. Usually, the default classloader will lazily load classes when they are needed.
Some classes cannot be relied on to be pre-loaded in any case however: Classes accessed via Class.forName(...) may not be determined until this code is actually exectued.
Among other options, for simple experiments, you can use static initializer code to have a look at the actual time and order in which classes are actually loaded; this code will be executed when the class is loaded for the first time; example:
class SomeClass {
static {
System.out.println("Class SomeClass was initialized.");
}
public SomeClass() {
...
}
...
}
Your example shows an executable jar, which is simply a normal java archive (jar) with an extra key/value pair in it's manifest file (located in folder "META_INF"). The key is "Main-Class" and the value the fully qualified classname of that class whose "main" method will be executed, if you "run" the jar just like in your example.
A jar is a zip file and you can have a look inside with every zip archive tool.
Whenever you compile a Java program the following steps takes place
First the Class Loader loads the class into the JVM.
After giving the command javac filename.java the compiler checks for compile time errors and if everything is fine then it will generate the .Class files(byte code).
This will be the first phase.
Later the interpreter checks for the runtime errors and if everything is fine without exceptions then the interpreter converts the byte code to executable code.
First phase in java is done by the JIT compiler(Just In Time).
I'm trying to write a decompiler for Java using reflection (all I need is the method signature information from a jar file passed in). I'm using a URLClassLoader to load classes from the jar file, and then pass that class on to my decompiler.
However, I've run into a problem. The jar I'm trying to read contains different versions of classes already loaded into my environment. So when I call
ClassLoader myClassLoader = URLClassLoader.newInstance(jars, null);
Class<?> classToDecompile = Class.forName(className, false, myClassLoader);
It returns not the class from my jar file, but the one that's already been loaded. Is there a way to load the class information for reflection only and get it from the jar passed in rather than from the JRE?
Edit:
The jar I'm trying to decompile contains classes in the java.lang package, which causes a security exception to be thrown:
java.lang.SecurityException: Prohibited package name: java.lang
ClassLoader.loadClass(String, boolean) - which URLClassLoader inherits - first checks for a previously-loaded class, and then, not finding any, checks with the parent class loader. You could override that method to bypass the check for a previously-loaded class. Not sure if you'd have to bypass the parent.
Mind you, this would be an evil class loader; you probably shouldn't use it for anything else.
You might also try reading the jar yourself, getting the contents of the class file (the byte codes), and calling ClassLoader.defineClass(name, byte[], int, int) yourself, supplying a unique name for the class. I think that's a better idea, actually.
Why wasting time when there is JAD? If you still want to achieve that you have to write your own class loader with child-first strategy.
So, I'm working in eclipse were everything compiles and runs correctly. However, when compiling under ant for the build server, A large number of tests fail with a NoSuchMethodError saying:
class A implements B
interface B extends C
C requires method getSyncID() // standard getter for an int field.
A.java contains getSyncID()
A.class contains getSyncID()
and yet the Error is still thrown.
Does anyone know how the hell this could happen? how to fix it.
This happens when class files get out of sync with each other; in other words, one was compiled to a new version while another one wasn't. Try cleaning and rebuilding from scratch.
The problem occurs when the class loader discovers that a method in one class (A) calls a method in another class (B) that does not exist. The root cause is that the class B that the class loader sees is different to the class B that the compiler saw when it compiled A.
The most common cause of this problem is as #MarkPeters says - that your ".class" files have gotten out of sync with the ".java" files and need to be recompiled from scratch.
Another possibility is that you have an old copy of some of the ".class" files on the classpath when you try to run the application.
But either way, you have to believe the classloader. If it says that the method is not there, then it is not there ... in the particular ".class" file that it is loading. If the method appears to be there in the ".class" file, then that is evidence that you are loading a different version of the file earlier in the classpath!