If I have two classes with same name say Matcher.java in two different jar in my classpath which one will be picked up by JVM , is there anyway I can suggest JVM to pick a specific one ?
Quoting Oracle:
Specification order
The order in which you specify multiple class path entries is
important. The Java interpreter will look for classes in the
directories in the order they appear in the class path variable. In
the example above, the Java interpreter will first look for a needed
class in the directory C:\java\MyClasses. Only if it doesn't find a
class with the proper name in that directory will the interpreter look
in the C:\java\OtherClasses directory.
The example mentioned:
C:> java -classpath C:\java\MyClasses;C:\java\OtherClasses ...
So yes, it will load the one appears in the classpath that specified first.
The first one found in the classpath. ie, the first jar containing your class will be used.
You can't control it from within the JVM, but you can control the classpath - make sure the one you want is listed/found first in the classpath.
there is a way for you to specify where the class should be picked from.. you can create your own class loader which would load classes according to your requirement.
you can use your class loaded in 2 ways
Pass it as a parameter to jvm (java -Djava.system.class.loader
=com.somepackage.YourCustomClassLoader com.somepackage.YourMainClass)
Use the class loader programatically to load a specific class (refer the links provided).
here are some useful links on class loading
Oracle - How to write your own class loader
A very nice post on writing custom class loader
Use the fully qualified path of the class when using it. But if you mean the class with the same name also has the same package - fix the class-path.
Related
I've already read the tutorial at ELKI documentation ( http://elki.dbs.ifi.lmu.de/wiki/Tutorial/DistanceFunctions ).
Unfortunately, I'm not grasping how to plug the generated .class with MiniGUI (or bash script for the provided .jar). How it can be done?
Ps: I know it sounds absolutely noob, but when I try to "type" the class name, as suggested, I get the error "The following parameters could not be processed: HammingDistance", for example.
ELKI will load classes via the standard Java Classloader. Therefore, they must be on the class path or they cannot be loaded. An example call (assuming your classes are in the bin folder) is java -cp elki.jar:bin/ de.lmu.ifi.dbs.elki.application.ELKILauncher
Parameters are interpreted as follows:
If there is a class with this name (including the package name!) it is used.
Otherwise, ELKI tries prepending the package name of the expected interface. Which enables shortcut names.
Otherwise, known classes (from the service files) are checked for aliases. For example, the Euclidean distance has an alias name of l2, Manhattan has an alias l1.
The class must have a parameterless public constructor or a inner public static class Parameterizer.
Input assistance is built as follows:
.jar files on the classpath are checked for service files in META-INF/elki/<interface>
folders on the classpath put you in development mode, where a recursive list is performed and all .class files are inspected. This is much slower, but removes the need to edit the service files. Discovered classes show up below the ones listed in the service file.
Furthermore, the package de.lmu.ifi.dbs.elki.application.internal includes classes that will inspect everything on your classpath, and will report e.g. classes that do not have a parameterless public constructor, or a inner public static class Parameterizer.
I have several jars containing the exact same class.
Lets say for example, A.jar and B.jar have the same class Hello.class. What will happen if I run the following:
java -classpath A.jar;B.jar com.testing.testcode
My question is whether it will run or not? As from my understanding class loader will scan the classpath and it will return whatever Hello.class it finds first.
I know I can avoid this problem if I use OSGi for loading a particular class.
But what my question is – whether this will run or not? Or the java -classpath A.jar;B.jar com.testing.testcode will break down for having two version of the same class.
This will work and the first Hello class in the classpath will be used, so in this case, the one from the A.jar
The class path is a "path". The first match is taken.
There is a boot class path which is examined first and this included the JARs in the JRE. BTW You can prepend these and override system classes but you are not supposed to and it might not be allowed in your license agreement.
Whenever you include the jar in your classpath, on startup/ on application class gets loaded into the container.
Now whether your code will work or not will depend on which jar gets loaded first in your container and accordingly if you are lucky then in your current setup it will work else you might get some error saying that method1 doesn't accept Type1 it should accept Type2.
Can I use ClassLoader's definePackage to override some packages from inside a jar?
For example, the application currently contains "javax.xml.bind" from abc.jar. If I call ClassLoader.definePackage(def.jar), in which the def.jar contains another version of javax.xml.bind, can I replace the classpath for the entire application to point to that of def.jar? Thanks.
No, you definitely can not use ClassLoader.definePackage to "override" some packages from inside a jar.
If I understand correctly, you want to make your JVM load any class under javax.xml.bind from def.jar while all other ones from abc.jar. In this case you can (in my personal order of preference):
1) Put def.jar before abc.jar in the CLASSPATH. This requires that no class you want loaded from abc.jar is present in def.jar.
2) Unzip def.jar, abc.jar, or both, and remove any conflicting classes so it is really irrelevant which jar comes first in the CLASSPATH. Then re-zip them. Or you can do this only on one jar and put it before the other.
3) Use a configurable classloader (sorry, no public domain one that I know of; let me know if you find one). This could be an interesting topic for an OS project, except that several initiatives with similar (but much broader) objectives are already ongoing, some at the core of the language.
4) Create a classloader for this purpose, probably extending the default one.
I am using Eclipse and I have got two libraries included in my project, foo.jar and bar.jar. In both JARs there is a class FooBar.java that includes the method getFoobar(Object xy).
Now I would like to load the method getFoobar(Object xy) either from foo.jar or from bar.jar on the basis of a properties file:
config.properties:
choice=foo
If choice==foo then the method of Foo.jar shall be picked, elsewise the method getFoobar(Object xy) from Bar.java. To make things more complicated the method getFoobar(Object xy) has in its method declaration objects loaded from another JAR which is included in foo.jar (and bar.jar respectively).
So my question is. How can I get the methods of the JARs respectively by Reflections? I have not yet found a solution. Is there a way to solve this issue?
Thank you.
Emrah
You can only load one or the other methods without getting complicated with class loaders. A simple workaround is to rename the package of one or both libraries with jarjar This allows you to have everything in foo.jar start with foo. and everything is bar.jar start with bar. and this avoids any confusion. I have seen this used to be able to load several version of Xerces based on configuration (and use them concurrently in the same app)
Write your ClassLoader that reads the property. Alternatively, you can use -D option in the jvm arguments
-Dchoice=foo
and in the code that loads the class from foo.jar or from bar.jar you can switch on this property value:
String choice = System.getProperty("choice");
if (Main.CHOICE_FOO.equalsIgnoreCase(choice)) {...}
...
OSGI can give you a similar capability.
How can I get the methods of the JARs respectively by Reflections?
You can't.
Reflection does not allow you to select between the two versions of the class. In fact, as far as the JVM is concerned, there is only one version; i.e. the one that appears earliest on the classpath.
You can solve this problem by defining multiple classloaders, each with a different classpath. However, there are complications:
If you manage to load both versions of the class into a running application, you will find that instances of the respective classes have different types, and you won't be able to convince the JVM otherwise.
When your application loads another class that statically depends on one of these classes, it will bind to the version of the class that is on the classpath of the dependent classes classloader. And you can't change that. So, uses of the class name in declarations / typecasts / etc in the dependent class will refer to the version of the class found by the dependent classes classloader, not the other one.
The upshot is that you can't use these same-named classes like regular classes ... especially if both versions need to be loaded in the same JVM. It is a better idea to give the two versions of the class different names. You don't gain anything by making the class names the same.
I have two .jar files having same package structure and same class name.
Eg. math.jar and state.jar
package structure is com.myorg.common
and both jars having class called Util
Now, When i use the class in program...Object of which class will be created at run time?
and what if i wanted to create an object of specific class? (that is from math.jar)
It will depend on the order in which the jar files appear in the classpath. I believe the one that appears first in the classpath will be used. Any one classloader can only have a single class with a particular fully-qualified name.
Basically, this is a really bad idea - don't have the same class in the same package in multiple places; it's just asking for trouble.