Java Class Loading Flow - java

can anyone give me an idea of how the class loading flow works?,
What i'm trying to say is that i need to understand what happend when a developer create a new object eg:
User user = new User();
where java goes to load the class, I try excluding a class from my build and setting the current thread class loader with a jar that contains the excluded class and run it with no good results.

ok, i found it. Thanks!.
Java looks for the classLoader of the class that contains it.

Related

How to load a java class outside the classpath?

I have a program where I want the user to be able to choose a .java class file from the file system, and then have that class loaded into the program.
I'm using a JFileChooser to allow the user to select a file. Then, I tried converting that file to a URL, and using a URLClassLoader to load the class (as suggested by these answers).
The problem is that, when I want to use the loadClass() method, I don't know the "full class name" of the class (e.g. java.lang.String). So, I don't know how to make this method work. Is there a way to get this class name? Or is there another way to do this?
Here is a sample of my code:
// Open the file chooser
JFileChooser fileChooser = new JFileChooser();
fileChooser.showOpenDialog(null);
File obtainedFile = fileChooser.getSelectedFile();
// Create the class loader from the file
URL classPath = obtainedFile.toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[] {classPath});
// Get the class from the loader
Class<?> theClassIWant = loader.loadClass("the file name"); // What do I put here??
Load a single class file is generally completely useless. Said class file isn't alone; it has more class files that are relevant. Even if you think 'nah, there is just one source file, do not worry about this', note that a single java file can easily generate multiple class files.
Thus, two options:
Don't load class files. Load jar files.
Use the usual mechanisms (META-INF/services or META-INF/MANIFEST.MF) to put some sort of class name in there so you know what to load. Then create a new classloader with the provided jar, load the manifest, figure out the main class, load that, and run it.
Attempt to determine the 'root' for the loaded class file and include that on the classpath.
This is quite difficult - the problem is, to 'load' a class file you need to tell the loader what the fully qualified name is of that class before it is loaded. But how do you know the fully qualified name? You can surmise the class name from the file (not quite always true, but usually), but the package is a more difficult issue.
You can open the class file yourself as a binary stream and write a basic class file format parser to get the fully qualified class name. Easy for an experienced java programmer. Quite tricky for someone new to java (which I gather you are, if you think this is a good idea).
You can also use existing tools to do this, such as bytebuddy or asm.
Finally, you can try a spaghetti-at-the-wall method: Keep travelling up the directory until it works. You know it isn't working if exceptions occur.
For example, to load C:\MyDir\Whatever\com\foo\MyApp.class, You first try creating a new classloader (see the API of URLClassLoader which is part of core java) using as root dir C:\MyDir\Whatever\com\foo, and then you ask it to load class MyApp.
If that works, great (but usually trying to load package-less classes is simply a non-starter, you're not supposed to do that, the CL API probably doesn't support it, intentionally, there is no fixing that).
If it doesn't, instead try C:\MyDir\Whatever\com, and load class foo.MyApp. If that doesn't work, try C:\MyDir\Whatever and load class com.foo.MyApp, and so on.
The considerable advantage is, if there is another class sitting right next to MyApp.class, and MyApp needs it, this will work fine.
You'll need to write a while loop (traversing the path structure using Paths.get and p.getParent()), catch the right exception, manipulate the path into the class name (using .replace and +), and, of course, create a class loader (URLClassLoader), load classes with it (invoke loadClass), and if you intend on running it, something like thatClass.getConstructor().newInstance() and then thatClass.getMethod("someMethod", String.class, /* all the other args here */).invoke(theInstanceYouJustMade, "param1", /*all other params */) to actually 'run' it, more to be found in the java.lang.reflect package.

NullPointer when getting resource as stream

I am trying to access a file from my project's directory, let's call it
src/main/project/foo/bar.txt
In class MyClass
But when I do:
InputStream is = MyClass.class.getResourceAsStream("bar.txt");
And do anything with the InputStream, e.g.
is.toString();
I get a NullPointerException
I have also tried:
MyClass.class.getResourceAsStream("/bar.txt");
and
MyClass.class.getResourceAsStream("./bar.txt");
Is there something extra I need to do as the file is not in the same package as the class in which I'm calling it? This application is deployed on TomCat, so absolute references to the filepath are impractical.
EDIT: To the person who flagged it as a duplicate of nullpointer, I know what a nullpointer is, obviously it can't find the resource. As to why that is the case, I need help figuring out.
if your class is at src/main/project/foo/MyClass.java MyClass.class.getResourceAsStream("bar.txt"); should be fine.
if your resource is in a different folder within the project than the class use:
MyClass.class.getClassLoader().getResource("main/project/foo/bar.txt");
in general:
MyClass.class.getClassLoader().getResource("package/<subpackage/>filename");
To my knowledge this works with any class anywhere within the same project.
MyClass.class.getResourceAsStream(); operates relative to the Location of myClass and you can't change that.

Access classes from package

I'm developing an android test app and i'm going to access all internal class of android.view package. android.view is a package that is present in jar file. I tried by loading package name but it doesn't display the classes if any one tried
this already, please help.
Here's what I tried so far:
public static void main() throws ClassNotFoundException{
Class o =Class.forName("android.view");
Class[] C=o.getDeclaredClasses();
for(int i=0;i<C.length;i++) {
Classname = C[i].getName();
ClassesDisplayActivity.your_array_list3.add(Classname);
Log.i("Ramu","classname "+ C[i].getName());
}
}
}
It is not possible to determine at runtime all of the classes that are in a package using a standard class loader.
You might have some luck with this library though:
https://code.google.com/p/reflections/
Package is not a class. You cannot call Class.forName() for package and access classes that belong to class using getDelcaredClasses().
I do not know what do you really need, so I'd recommend you to explain this in separate question. probably you will receive better solutions.
However if you really need this you have to do the following:
Get your classpath by calling System.getProperty(java.class.path)
split this property to its elements by colon
iterate over the list and read each resource. If resource is jar you can use ZipInputStream, if it is a directory use File class.
filter list of resources you got at #3.
Fortunately you can use 3rd party library named Reflections that helps you to do all this without writing code.

NoClassDefFoundError exception in my thread

I get this error:
Exception in thread "http-server" java.lang.NoClassDefFoundError: org/w3c/jigmonitor/ReplyServer
but I don't undestand why. Could someone explain why does this happen?
This is the class that causes the problem:
public class ReplyServer implements Serializable
{
public ReplyServer()
{
super();
}
}
It looks like the class you're defining isn't being found by something that's trying to load it. In my experience this is caused by one of three problems:
Your package declaration for the class is not correct. In this case something on the http-sever thread is expecting your class to be declared in the package org.w3c.jigmonitor.
Your source file is not located in the correct directory. In this case, your source file should be located in a directory structure like "org/w3c/jigmonitor/", providing that's the package you actually want.
The path of the compiled class for ReplyServer is not in the classpath of your JVM. You can check this by looking at the classpath used to start your JVM and seeing if the class is actually there or not. In most generic setups servlet setups there will be a "WEB-INF/classes" folder for you to go poke around in.
Good luck!
(The link David posted gives a ton of information on this type of issue and the possible causes. I would recommend tucking that away for later)

Xcode cannot find a java class which I'm trying to extend

I'm working on a Java project which was written by someone else. This person made a hierarchy of folders inside the 'src' folder. I've added a new java class into one of those folders and defined it as 'XmlFile.java'.
Then, I'm trying to have it extend a previously written class 'GenericFile.java' by writing
package //Same package GenericFile is in
public class XmlFile extends GenericFile
{
...
}
When I try to compile the project it gives me the error
Cannot find symbol
and refers me to the line
public class XmlFile extends GenericFile
if I take out
extends GenericFile
everything compiles great.
I also notice after adding the new file (XmlFile.java) I cannot delete it (the option in Edit->Delete is not selectable for that file, or for any files/folders created by the person from whom I got the project).
Is there some sort of permission issue here or some hidden scope issue caused by the permissions being strange or what?
Please help me
Cheers,
WhiteTiger
I admit I am not an expert enough to figure out "Cannot find symbol" from a Java compiler, but since there is no other answer, here is a sneaky idea -
If GenericFile is a working and useful abstract class, there has to be at least one other class (hopefully working) that extends it. Since you have the source code, find out one such file, copy it to XmlFile.java, edit it to change the constructor name to XmlFile and try to compile it. If it compiles, start from there. If not, you will know where the problem lies.
Just trying to help! Good luck, - M.S.

Categories