How can I load a *.java class file into my java app and create an object based on that class file?
You can do it by using classes inside javax.tools. You will have a ToolProvider class from which you can obtain a compiler instance and compile code at runtime. Later you will load .class files just compiled separately with a ClassLoader unless you obtain directly a binary code for the class and you are able to istantiate it directly.
Take a look here
Try Janino's SimpleCompiler. Simple example, assuming you're compiling a class with a public no-arg constructor.
import org.codehaus.janino.SimpleCompiler;
public class JaninoSimpleTest
{
public static void main(String[] args) throws Throwable
{
String filename = args[0];
String className = args[1];
SimpleCompiler compiler = new SimpleCompiler(filename);
ClassLoader loader = compiler.getClassLoader();
Class compClass = loader.loadClass(className);
Object instance = compClass.newInstance();
}
}
i Think this will help : Package Summary
Or Simple Comipler .
You cannot. The .java file needs to be compiled into a .class so that you can use it.
Related
System.out.println(javaClass.getSuperclassName());
JavaClass javaClass1 = javaClass.getSuperClass();
the first line output the name of the class: RestController
The second line throws Exception:
java.lang.ClassNotFoundException: Exception while looking for class example.RestController: java.io.IOException: Couldn't find: example/RestController.class
So, you're using The Byte Code Engineering Library (Apache Commons BCEL™) to load classes from a Jar file (by filename) and want to print the entire call graph with the following github project.
This works just fine, until you want to ask for the superclass of a class that was found in your jar file.
So bcel will load a .class file, and store all it can read from the class file in a JavaClass model. This is for example the name, some flags, the super class name, the declared methods etc.
For example inspect the following java code;
JavaClass stringClass = Repository.lookupClass("java.lang.String");
System.out.println(stringClass);
with output:
public final class java.lang.String extends java.lang.Object
implements java.io.Serializable, java.lang.Comparable, java.lang.CharSequence
file name java.lang.String
compiled from String.java
compiler version 52.0
access flags 49
constant pool 540 entries
ACC_SUPER flag true
Attribute(s):
SourceFile: String.java
etc...
So bcel knows that the superclass is java.lang.Object, but it has not loaded any of the classes at this point! For JRE classes this is of course moot, but for the classes from your Jar file this is a problem.
Because org.apache.bcel.classfile.JavaClass#getSuperclassName will just return the String value that it found as the super class in the .class file. Again this class was not loaded, so the Repository doesn't know about it.
When you then ask for the org.apache.bcel.classfile.JavaClass#getSuperClass, it will try to find it like so:
public JavaClass getSuperClass() throws ClassNotFoundException {
return "java.lang.Object".equals(this.getClassName()) ? null : this.repository.loadClass(this.getSuperclassName());
}
Bcel will try to load it from its Respository, and if the class is unknown, it will delegate the loading to the current ClassPath. Since you're just inputting a File pointing to a Jar, this will fail with the ClassNotFoundException.
There are two ways to you can solve this:
Put the jar file(s) on your classpath; for example via Including all the jars in a directory within the Java classpath
First load all the jar files into the Repository of bcel, so that it knows these classes exist. If we stay in the JCallGraph example from github, that would look something like this:
// ... JCallGraph code from Github above this point
try (JarFile jar = new JarFile(f)) {
// extra stream over jar entries
Stream<JarEntry> jarEntryStream = enumerationAsStream(jar.entries());
jarEntryStream.filter(jarEntry -> jarEntry.getName().endsWith(".class"))
.forEach(jarEntry -> {
ClassParser cp = new ClassParser(jarFileName, jarEntry.getName());
try {
// here we tell BCEL this class exists
Repository.addClass(cp.parse());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
});
// ... back to the JCallGraph code from Github
Stream<JarEntry> entries = enumerationAsStream(jar.entries());
Note that if you have multiple jar files, or super classes coming from external dependencies, these all need to be on the classpath (1) or loaded in bcel first (2) before you can load the superclass.
I need to use a .jar library, given by my teacher, to code for my Java class.
I am using VS Code, with the Java Extension Pack installed, for Java Project Management.
Can someone please explain me step by step how is it possible to import the .jar library, in order to use the classes defined by my teacher.
I have tried to copy the .jar in the lib folder and then add the reference, but it still did not work. I also know that I have to declare the classpath, but when I create the Java Project the .classpath file is not created automatically.
Thanks already!
First you should examine the classes in .jar file. Then you should load that class as,
Class<?> c1 = Class.forName("java.lang.String");
Then after you can use that class by calling that Class reference type variable.
See this example as well,
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
// get the Class instance using forName method
Class c1 = Class.forName("java.lang.String");
System.out.print("Class represented by c1: "+ c1.toString());
} }
Try to understand the code and implement proper solution to your project.
Good Luck.
I started to learn Java couple days ago. And I have this burning question. Is empty .java file name a valid source file name?
.java
Yes, save your java file by .java then compile it by javac .java and run by java yourclassname
class X {
public static void main(String args[]) {
System.out.println("Hello World");
}
}
to compile - javac .java
to execute - java X
Yes it's working because java compiler doesn't consider it saves file name or not except our class having public specified we can save any name or empty but when ever trying to execute we must use our class name because, jvm creates byte code ourclassname.class so we using
java className
Yes Empty .java file name works, but class must not be public, it means that it must be default.
If class is public then following error occour:
D:\Testjavac>javac .java
.java:1: error: class Empty is public, should be declared in a file named Empty.
java
public class Empty
^
1 error
Yes You can have .java file withought nay name . you have to compile it by javac .java(it compile successfuly) and run it by java clasnname.(so you must provide a class name)
Yes, but don't do this often.
You can't create any classes in that file that are public or private, so any class that made use of any class defined here would have to be in the same package.
at anytime you can have only one public class in the file and if you use public class then that class name should be the file name.
I'd like to be able to load a class(es) from a known directory whenever a compiled .class file appears in that particular directory. However the I'd like the .class to be loaded regardless of what the package decleration is in its .java file. For example I have this class which I wish to load:
package com.javaloading.test;
public class SomeClassInPackage {
private String name = "The name of this Class is SomeClass.";
public String getName(){
return name;
}
}
And it is in the package com.javaloading.test. I then want to load it using this class:
public class GetPackage {
public static void main(String[] args){
new GetPackage().loadMyClass();
}
public void loadMyClass(){
// Get the current class loader
ClassLoader cl = getClass().getClassLoader();
try {
Object o = cl.loadClass("SomeClassInPackage");
System.out.println("Class loaded!");
} catch (ClassNotFoundException ex){
System.out.println("Could not load class");
}
}
}
If I put the .class files of both the above Classes into the same directory and run GetPackage it results in the error
Exception in thread "main" java.lang.NoClassDefFoundError:
SomeClassInPackage (wrong name:
com/javaloading/test/SomeClassInPackage
I need to be able to load a class (from a file) regardless of it's declared package and without having to actually know its package. I would then examine the loaded class for its package information. Is this possible using the System ClassLoader or a custom ClassLoader or is it impossible without having knowledge of the package structure? If it's possible any advice is appreciated.
It is impossible to load the class without its respective package structure, means if you want to load the class then it must be placed in the folder that is correspond to its packages name or that class is in a jar file but in same folder structure.
But lets say you want to load the classes which is external means not in the class path where this program gets executed from and you want to load it in current class loader during execution. Refer to this link How to load the classes at runtime. This will also gives answer to your next question where you want to load the classes which is selected by the program based on its name or package.
I have wrote some code to compile a Java source code. It then produces the .class file. The problem is how do I run it?
For example, I am ok with the name of the program and class being set, I've used prog p = new prog(), in this case, however, the class file does not yet exist until I compile it. Not really sure what to do. Can someone give me an advice?
btw, the class looks like this:
public void compile{
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int compilationResult = compiler.run(null, null, null, fileToCompile);
}
public void run(){
Prog prog = new Prog();
prog.run();
}
If you just want to run it, you could launch a java process using
Runtime.exec or ProcessBuilder. These will create a seperate java process to run your java program. This is more likely what you want. You can essentially do the equivelant of:
>java someClass
from within your application. This link may help.
If you want to actually load the classfile and use it in your current application, I think something along the lines of this, or dynamically loading Java Classes ought to help. Basically (directly from the link, slightly modified):
public class MainClass {
public static void main(String[] args){
ClassLoader classLoader = MainClass.class.getClassLoader();
try {
Class aClass = classLoader.loadClass("MyClass");
System.out.println("aClass.getName() = " + aClass.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Once you loaded the class, you have a Class object, and you can create an instance of the class represented by aClass by calling aClass.newInstance(), which is like
MyClass newObj = new MyClass()
Or you can use any of the other methods the Class object exposes.
As pointed out by davmac, the code sample above presumes that the code you're loading is on your applications classpath. If the class files you want to run are not in your classpath, you might want to look into URLClassLoader
Load it by URLClassLoader.
File root = new File("/java"); // The package root.
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName("test.Test", true, classLoader); // Assuming package test and class Test.
Object instance = cls.newInstance();
// ...
See also:
How do I instantiate a class dynamically in Java?
You need to create a classloader (a URLClassLoader will probably be fine) which will load the just-compiled class file. (So for a URLClassLoader, the compilation output path should be one of the URLs).
Then, load the compiled class using the classloader, and execute it using reflection.
Class c = cl.loadClass("ClassName");
... etc.