The Java standard/system libraries (java.*, javax.*, etc.) are stored in lib/rt.jar inside each JRE distribution.
Say I have an application that I have compiled and jarred into myapp.jar. This JAR only contains my app's class files, and merely references system classes like System, File, Runtime, Thread, String, Boolean, etc.
So when I run my app, say via java -jar myapp.jar, the JVM is obviously doing so last minute linking (or something) where it is executing the bytecode of my class files (inside myapp.jar) and then "jumping" into lib/rt.jar to run bytecode located there. I would imagine the process is the same if myapp.jar depends on other JARs provided on the runtime classpath.
My question is: what is this "linking" process called, and how does it essentially work?
That rt.jar is part of the bootstrap classpath, a parent of the usual classpath you already know and that you configure when you use the -cp option (you can actually change the bootstrap classpath too using the -Xbootclasspath option to load, for example, a custom Java runtime).
See Oracle documentation for a detailed description of how classes are searched/loaded from the system defined classpaths hierarchy.
Now, the additional questions you seemed to have:
How is the archive actually found?
It's simply hardcoded. If the java binary is located in <common_root>/bin/java, rt.jar will be searched in <common_root>/lib/rt.jar.
How is the "linking" performed?
On the JVM there is no actual linking, the classes are dynamically loaded using a mechanism based on a hierarchy of ClassLoader that are the software components that actually do the class file loading/parsing. When you try to load a class, the search starts from the application-facing default classloader(or a child classloader if you have defined one) and if the class cannot be loaded the loading attempt is repeated with a parent classloader until the bootstrap classloader is reached.
If the class is found, the .class file is loaded, parsed and internal structures representing the class and its data are created.Once the class is loaded a new instance can be created.
If instead, even the boot classloader could not load your class a user-visible ClassNotFoundException is thrown.
Related
How do I determine the name of the jar that is dynamically loading my jar? Is it possible? I have attempted many variants using ClassLoader but with no success.
Thanks in advance.
Let me explain why I need the name of the "loader jar". In our container we have the following lines:
URLClassLoader classLoader = new URLClassLoader(new URL[] { artifact.getFile().toURI().toURL() });
Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, artifact.getArtifact().getFile().toURI().toURL());
Class<?> processorClass = classLoader.loadClass(className);
Object processorClassInstance = processorClass.newInstance();
When the loaded class is instantiated, newInstance above, it's properties files is external to the jar the class resides. The configuration files are in a directory named after the container jar that contains the class that executed the lines of code above. So, if the deployed container jar is called RedcapTDP.jar the configuration files are in "C:...\RedcapTDP". When the RedcapTDP.jar is deployed it dynamically loads the configured maven artifact which in turn will read it's configuration file from the RedcapTDP directory.
I hope that makes it clear!
How do I determine the name of the jar that is dynamically loading my jar? Is it possible?
Taking you literally, no, it is clearly impossible. In fact, it doesn't even make sense. Java does not "load" Jars at all, though it may load one or more classes contained within a jar. When it does so, it is the VM loading the class, not any jar loading it.
Interpreting you a bit more liberally, perhaps you are asking "how do I determine the class whose dependency on one of the classes in my jar is causing my class to be loaded, and how do I determine from which jar file that other class was loaded?" Unless your control extends beyond the classes in your jar, however, this is again impossible.
Class loading is a separate step preceding class initialization, and class initialization is the first point at which there is any opportunity to execute any code contained in your class. Thus, class loading is no longer ongoing when your classes first get a chance to inquire about anything. Moreover, classes are not necessarily loaded from jars at all, and in any event, they do not carry information about the source from which they were loaded.
I could perhaps go further afield with speculations about what you may mean to ask, but I don't see any interpretation of the question that affords an answer different from "no, it is not possible."
JARs don't load JARs. A jar file is just a meaningless container that helps holding class files and other resources together. Classes are loaded by a class loader(s) from a class path provided to the jvm. What you're trying to do is not possible. Maybe you can explain what you're trying to achieve and perhaps there is a better way to do it.
In a standard JVM I can re-order my classpath to "hide" similar classes (move desired implementation of a class/interface to the front of the classpath). How I can achieve this behaviour in the internal database JVM (e.g. 11g)? Is this the order of loading the classes with "loadjava"?
When you use the loadJava utility to load a class there is only a single path on the class-path.
If you load a class that has the same name and class path as a previous class then it will ignore the newer class unless you specify the -force option:
-force Forces files to be loaded, even if they match digest table entries.
In which case it will overwrite the earlier entry (it will not load two copies of the class).
So, no, you cannot hide duplicate classes by re-ordering the class-path (as you can with external JVMs) as there is only a single path on the class-path within the internal JVM used by Oracle.
I've created a project that dynamically writes, compiles and instantiates a new java class at runtime and it works just fine when I run this on the command line or within eclipse. Ultimately my goal is to create a technology very similar to JSP; the user provides a "template" file and I translate it into a java class and instantiate that class. My problem is that I can't seem to instantiate the newly compiled class when in the context of a web application.
The core of my problem is that I don't know where to put my compiled classes so that I can immediately instantiate them.
Here are my goals:
This will be a generic tool for other developers so it can't be specific to my filesystem or my java container.
If the user undeploys their webapp from the container it should also remove these generated classfiles.
Here are my thoughts but I have never done anything like this before:
Do I put these generated classes into one of the existing entries of the classpath, if so which one? Should I let the user provide a path and then my library will add this path onto the classpath? Maybe they provide a path and I just use a custom class loader to read them from that path? The user already provides the path of their "templates" (ex. WEB-INF/templates) so should I put my compiled classes with the original templates? My understanding is that translated JSP files are stored in a proprietary place specific to that java container and therefore I can not follow in the footsteps of JSP files.
Ahh! I'm overwhelmed! Maybe there's an open source java library that does something similar and I can study it to determine where it puts it's generated files??
Basically you will need to define your own classloader and do the loading from there.
See How do you change the CLASSPATH within Java?
I was curious about what all locations JVM looks for executing a program? I'm more interested in understanding in what sequence and where does JVM look for class files, like does it look into java libs, extension libs, classpath any directory like the current directory from where the java is invoked? I'm more interested in JVM behaviour and not how class loader load class, which I know has parent delegation mechanism till root.
If a class is executed from directory where the compiled class is kept on file system and also in a jar file in the same directory, would JVM load both or just one and which one?
Say you have a thread unsafe Vector and if we compare it performance to ArrayList, which one would be better and why?
How classes are found.
Answer is here:
http://docs.oracle.com/javase/1.5.0/docs/tooldocs/findingclasses.html
Answer for point 2:
Order of finding classes is as follows:
classes or packages in current directory.
classes found from CLASSPATH environment variable. [overrides 1]
classes found from -classpath command line option. [overrides 1,2]
classes found from jar archives specified via -jar command line option [overrides 1,2,3]
So if you use -jar option while running, classes come from jarfile.
Only one class is loaded though.
Without using any additional classloader:
Search order for a JVM:
Runtime classes (basically, rt.jar in $JRE_HOME/lib`)
Extension classes (some JARs in $JRE_HOME/lib/ext`)
Classpath, in order. There are four possibilities for specifying classpath:
If -jar was specified, then that JAR is in the classpath. Whatever classpath is declared as classpath in META-INF/MANIFEST.MF is also considered.
Else, if -cp was specified, that is the classpath.
Else, if $CLASSPATH is set, that is the classpath.
Else, the current directory from which java has been launched is the classpath.
So, if I specify -cp src/A.jar:src/B.jar, then A.jar will be searched first, then B.jar
The JVM loads only the class that is found first, according to the order in which the directories/JARs are declared in the classpath. This is important if you use -cp or $CLASSPATH.
In single thread scenarios and with recent JVMs, Vector and ArrayList should have similar performance (ArrayList should perform slightly better as it is not synchronized, but locking is fast currently when there is no contention, so the difference should be small). Anyway, Vector is obsolete: don't use it in new code.
I believe Java looks in the current directory, then at the class path, per the "-cp" VM argument. You can put any combination of folders of classes (e.g. /project/bin/com/putable), specific class files (e.g. /project/bin/com/putable/MyClass.class), and JAR files (e.g. /project/lib/MyJar.jar) on the class path. Locations are separated by either a colon (Unix-based OSes) or semicolon (Windows-based OSes). So anything on the classpath is fair game for Java to look at when obtaining class definitions. With respect to sequence, classes are loaded lazily. So they only get loaded when your application first requires them. If your application doesn't require a certain class during the duration of its runtime, then that class will NEVER get loaded.
If you don't put anything on the class path, I think Java will load from the class file and not the Jar. If you specify one or the other on the classpath, then that's the place Java will look for. If you put both on the classpath, Java's class-loading behavior is undefined and it could pick either, depending on the JVM implementation.
Depends on what you want to do. Vectors are actually always thread safe, per the Java API, so if you don't require concurrent access, the ArrayList will be faster. Vectors and ArrayLists are both backed by arrays, but they increase capacity at different rates (Vector capacity doubles whenever the end is reached and more space is needed, but ArrayList increases by 50%). Depending on how often you have to grow or shrink, the answer will vary. Check out this link for more info:
http://www.javaworld.com/javaworld/javaqa/2001-06/03-qa-0622-vector.html
I'm more interested in JVM behaviour and not how class loader load
class
Sorry, but this is nonsensical.
Because the answer is that the JVM creates a class loader and let's this class loader load the classes.
So, in order to understand the "JVM behaviour" you need to understand the class loader behaviour.
But maybe your question was: how does the JVM create the system class loader?
The accepted answer is already correct but there is a more detailed and updated official spec in How Classes are Found.
Some caveats as:
A class file has a subpath name that reflects the class's fully-qualified name. For example, if the class com.mypackage.MyClass is stored under /myclasses, then /myclasses must be in the user class path and the full path to the class file must be /myclasses/com/mypackage/MyClass.class. If the class is stored in an archive named myclasses.jar, then myclasses.jar must be in the user class path, and the class file must be stored in the archive as com/mypackage/MyClass.class.
And the priorities in How the Java Launcher Finds User Classes
The default value, ".", meaning that user class files are all the class files in the current directory (or under it, if in a package).
The value of the CLASSPATH environment variable, which overrides the default value.
The value of the -cp or -classpath command line option, which overrides both the default value and the CLASSPATH value.
The JAR archive specified by the -jar option, which overrides all other values. If this option is used, all user classes must come
from the specified archive.
When we refer to a class className in jar, how does it know whether it's defined or not when there's no header files(like in c/c++) ?
Java works with classloaders. Classes are needed for compilation, since it will perform static type checking to ensure that you are using the correct signatures of every method.
After compiling them, though, they are not linked like you have in a C/C++ compiler so basically every .class file is standalone. Of course this means that you will have to provide compiled classed used by your program when you are going to execute it. So it's a little bit different from how C and C++ prepare executables. You don't actually have a linking phase at all, it is not needed.
The classloader will dinamically load them by adding them to the runtime base used by the JVM.
Actually there are many classloaders that are used by the JVM that have different permissions and properties, you can also invoke it explicitly to ask for a class to be loaded. What happens can also be a sort of "lazy" loading in which the compiled .class code is loaded just when needed (and this loading process can throw a ClassNotFoundException if the asked class is not inside the classpath)
When you run the Java compiler or your application itself, you can specify a classpath which lists all the jars and directories you're loading classes from. A jar just contains a bunch of class files; these files have enough metadata in them that no extra header files are necessary.
The classes in the jar file contain all the required information (class names, method signatures etc) so header files are not needed.
When you compile multiple classes javac is clever enough to compile dependencies automatically so the system still works.
It looks at the classpath and tries to load the class from there to get its definition.
Java files are compiled into class files which are java bytecode. These class files reside in a file structure where the top level is pointed to by the classpath variable. Compiling in C/C++ creates object files which can be linked into executable binaries. Java only compiles into bytecode files which are pulled in by the JVM at runtime. The following provide more explanation.
http://en.wikipedia.org/wiki/Java_bytecode
http://en.wikipedia.org/wiki/Java_compiler
http://en.wikipedia.org/wiki/Java_Virtual_Machine