Controlling the loading of Java class in CLASSPATH - java

I am trying to apply patch using classpath approach, I mean I am adding modified class files as jar file, and while classes are getting loaded new version of classes are loaded. Therefore application is patched without changing original jar file.
The following classpath definition works fine;
java -cp patch/patch.jar;bin/ com.test.PatchClasspath
but when order of lib classes are changed it does not work.(as usual)
java -cp bin/;patch/patch.jar com.test.PatchClasspath
I would like to know is there a JVM parameter which indicates the lib loading order?
EDITED:
I amd modifying Util->print() method to verify patch is applied.
package com.test;
public class PatchClasspath {
public static void main(String[] args) {
Util util = new Util();
util.print();
}
}
package com.test;
public class Util {
public void print(){
System.out.println("Version-1");
}
}
Thanks.

There is no such parameter indicate the lib loading order in JVM (I believe), however, the java -classpath option itself will determine the class loading order base on the paths you put.
JDK document explain this:
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/classpath.html
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.

Try -verbose:class, this will show you all the loaded classes, in which order they were loaded and from which jar they were loaded.
To control the order of classes loaded, you can modify the order of jars in your classpath, using the java -cp. I do not think there is a way howto control the order of classes being loaded from a specific jar.
To verify that the patch is applied, a simple/dummy solution is to add a static field with the System.out.println(""). For Example:
static {
System.out.println("[DBG] : My Patch v1.0 is loaded.");
}

Related

What's the differences between the build function of Eclipse and javac?

I find a project in Eclipse has it own class path.
If i use maven create a new web project.
System.getProperty("java.class.path");
When i print the result,
I find the class path contains G:\newtool\workspace\springmvc\target\classes.
Who can explain the principles behind it.Why the class path is this directory.
Is the build function of Eclipse same as the command,javac -classpath?
And i find another question.
public class KnightMain {
public static void main(String[] args) throws Exception {
System.setProperty("java.class.path","G:/newtool/workspace;G:/newtool");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("knight.xml");
Knight knight = context.getBean(Knight.class);
knight.embarkOnQuest();
String s[] = System.getProperty("java.class.path").split(";");
for (String string : s) {
System.out.println(string);
}
context.close();
}
}
Although i set the class path to other directory where the knight.xml is not exist.But ClassPathXmlApplicationContext find it finally.Why the
System.setProperty("java.class.path","G:/newtool/workspace;G:/newtool");
makes no difference.Although the print result is:
G:/newtool/workspace G:/newtool
Two different tools, two different concepts.
First of all eclipse has its own java compiler. It is not using javac in any way. And the class path used by the eclipse compiler, is, surprise, what you told it to be.
In other words: when you create your eclipse projects, you configure its build path. The Build Path determines which libraries, other projects, ... should be imported, exported, ... and so on.
Whereas, when you open your command like shell, and you call javac directly, the classpath is based on the settings that you make there; for example by calling
javac -classpath /some/directory/with/classes:/some/bla.jar
Or in your case: you are using maven, which comes with its pre-defined rules, project dependencies, and so on. Thus your classpath there depends on the conventions/rules that maven applies for "java web projects". Thus: if you want to understand what maven is doing for you: you have to study the maven documentation for the features you are using there!
EDIT: I think what you are actually trying can't work. I think that this specific system property is more of a "read only" value. Meaning: you can use it to understand the current classpath. But writing the property will not change the classpath of the JVM you are currently running in.
Actually, that makes a lot of sense: if any piece of java code could change the classpath on the fly, that screams "security problem" all over the place! As that would allow you to completely change where the JVM would be loading its classes from.
The java.class.path property is used by JVM to locate classes and JAR files for loading. This system property is common for most available JVMs including Oracle and IBM implementations. This property is used by the default class loader, but not all custom class loaders. You can implement your own class loader, that ignores java.class.path and is using some other property to locate loader-specific packages. One example is Eclipse. Eclipse core has a custom class loader that is not using java.class.path.

How to plug custom distances with ELKI?

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.

Java: Two jars in project with same class.

I have a java project that is using two imported jars with the same class (com.sun.mail.imap.IMAPFolder). Is there a way to explicitly say which jar to use when importing the class? Using:
import com.sun.mail.imap.IMAPFolder;
would seem to use the class in order of build path order but this does not seem to be the case for some reason causing
Exception in thread "main" java.lang.reflect.InvocationTargetException
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:616)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.NoSuchMethodError: com.sun.mail.imap.IMAPFolder.idle()V
at com.woodbury.GCM.HelperGmailMonitor.doEmail(HelperGmailMonitor.java:104)
at com.woodbury.GCM.Launch.listen(Launch.java:16)
at com.woodbury.GCM.Launch.main(Launch.java:10)
... 5 more
at runtime. I am building the project in eclipse.
When a class is loaded, the first implementation that matches the requested fully qualified name that is visible to the relevant ClassLoader is what gets returned. Any other implementations with the same fully qualified name are effectively hidden to that ClassLoader.
What this means in a standard Java SE application is that the first code base (e.g. a jar) listed on the classpath with the required class, provides it, and all other code bases' implementations of the same fully qualified class are hidden.
Example:
Assume that A.jar contains the compiled class
package com.stackoverflow.example;
public class Hello {
public static String getGreeting(){
return "Hello, A!"
}
}
Assume that B.jar contains the compiled class
package com.stackoverflow.example
public class Hello {
public static String getGreeting(){
return "Hello, B!"
}
}
Note that in both of the above classes have the same fully qualified name.
Assume main class is
import com.stackoverflow.example.Hello;
public class ExampleMain {
public static void main(String[] args){
System.out.println(Hello.getGreeting());
}
}
If I were to invoke my program with
java -cp A.jar:B.jar ExampleMain
the output is: Hello, A!
If I reverse the classpath like so
java -cp B.jar:A.jar ExampleMain
the output is: Hello, B!
You cannot do what you ask just in your Java source. Java was not designed for that.
This is a bad situation which can only be handled reliably with custom class loaders, each providing one of the jars you need. Since you are asking this question in the first place this is probably not the way you should go yet since that opens up a LOT of new time consuming problems.
I would strongly suggest you find out why you have two different versions of the same jar in your classpath and rework your program so you only need one version.
Yes, there is a way to fix the issue. In my scenario, I have two classes with same name and same path and eclipse always imports the wrong one. What I have done is changing the jar order in the build path and eclipse will pick the first one in the build path.
If you are using an IDE, you can set the order of exporting the files to the class loader.
I work on eclipse and I use maven. When I install the project using maven, it produced many extra jars (which i hadnt defined in my dependencies) and there was a file org.w3c.dom.Element which was present in 2 jar files and 3rd instance of the same file was also in JRE7.
In order to make sure the correct file is picked up, all I had to do was to go to Java Build Path -> Order and Export. Select the Jar file I wanted the classloader to give more preference and move it up with the button "Up".
This is how it looks.
Please note that this image is for eclipse. But for other IDEs there would definitely be a similar way to work this out.
1) In general: Yes you can have the same class in different .jar files: you just disambiguate them with a fully qualified package name. The "Date" class (present in java.util and java.sql) is a good example.
2) If you have two DIFFERENT .jar files that have the SAME fully qualified package names ... chances are, you've got a conflict. Even if you can hack around the InvocationTargetException by playing with the class loader, you might still encounter other problems. In this case, it sounds like maybe your two .jar files have two different implementations of the JavaMail API. I don't know.
3) The safest bet is to satisfy all your program's references WITHOUT risking a conflict. I believe if you took took the "official" .jar's from Oracle's JavaMail web page, you can do this:
https://java.net/projects/javamail/pages/Home
'Hope that helps!

Using class files from a jar file that already has the path built

I'm a little lost here. We were given a jar file which contained 3 different .class files in it. I successfully built the path to the jar file, but I don't know how to use them. The class files obviously contain methods that can be used, but I've never worked with a jar file before so I don't know how to use them. I'm not sure if I have to import them somehow, how to instantiate them or anything. I have searched for tutorials to no avail.
All I'm looking for is some guidance so I can get moving on this project. If it is a case where I have to import them somehow how would I do it? For example, I have WikiEdits.class contained in WikiEdits.jar. The name of my main class is P2. Can someone show me a brief example of how this works?
Add the jar to your classpath, if you are using an IDE.
Then, a java class that uses it would look like something like this:
package p2;
import blah.WikiEdits; //references a class in the jar
public final class P2 { //(this is a strange name for a class, by the way)
public static void main(String... args){
//builds a new object of the given class
WikiEdits thing = new WikiEdits();
}
}
If you are using the command line, these examples may help:
http://www.javapractices.com/topic/TopicAction.do?Id=243
you need to add WikiEdits.jat to your path project, then import and instanciate the class.
import WikiEdits
P2 p = new P2();
p.somemethod();
Static class:
WikiEdit.someMethod();
In your java class add the relevant imports from the jar. And then from command line, you can compile and run your class using the classes from jar by definining the right classpath:
Compilation
on windows:
javac -cp .;pathtoyourjar YourClass.java
on linux:
javac -cp .:pathtoyourjar YourClass.java
Execution
on windows:
java -cp .;pathtoyourjar YourClass
on linux:
java -cp .:pathtoyourjar YourClass
If you are using Eclipse then follow this link to know the steps to add jar to your project:
http://www.cs.duke.edu/courses/cps004g/fall05/assign/final/addlibrary.html

Two classes with same name in classpath

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.

Categories