JNorr44
JNorr44

Reputation: 274

Defining a class in java using a string

Everyone always immediately says Class.forName, but this is not that!!!

Ok, so I am trying to get a bunch of text off a website and compile it into a class. So far I have been able to get the text from the website, but I cannot define it for some reason.

Please take a look:

Main class: (Driver.java)

public class Driver {
public static final Pattern packageDeclaration = Pattern.compile("package");

public static void main(String[] args) throws Exception {
    System.out.print("Enter the URL of the main class:  ");
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String stringURL = br.readLine();
    String text = getURLText(new URL(stringURL));
    ByteClass mainClass = new ByteClass("Main", text.getBytes());
    mainClass.clazz.getMethod("run", null).invoke(mainClass.clazz, null);
}

public static String getURLText(URL url) throws IOException {
    StringBuilder lineGatherer = new StringBuilder();
    BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
    String line;
    while ((line = in.readLine()) != null) {
        lineGatherer.append(line);
    }
    in.close();
    return lineGatherer.toString();
}

}

And ByteClass.java:

public class ByteClass {
private ArrayList<Byte> nonarraybytes = new ArrayList<Byte>();
public byte[] bytes;
public String[] lines;
public Class<?> clazz;

public ByteClass(String name, byte[] bytes) {
    for (byte b : bytes)
        nonarraybytes.add(b);
    bytes = new byte[nonarraybytes.size()];
    for (int i = 0; i < bytes.length; i++)
        bytes[i] = nonarraybytes.get(i);
    clazz = define(name, bytes);
}

protected Class<?> define(String name, byte[] bytes) {
    return new ClassLoader() {
        public Class<?> defineClass(String name, byte[] bytes) {
            return super.defineClass(name, bytes, 0, bytes.length);
        }
    }.defineClass(name, bytes);
}

}

So, here's the problem:

Enter the URL of the main class:  https://raw.github.com/JamesNorris/Ablockalypse/master/src/main/java/com/github/JamesNorris/Threading/FakeBeaconThread.java
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1885430635 in class file Main
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(Unknown Source)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at com.github.ByteClass$1.defineClass(ByteClass.java:134)
    at com.github.ByteClass.define(ByteClass.java:136)
    at com.github.ByteClass.<init>(ByteClass.java:21)
    at com.github.Driver.main(Driver.java:20)

Upvotes: 0

Views: 301

Answers (3)

Jiri Kremser
Jiri Kremser

Reputation: 12837

At some point you have to use the compiler. The good news is that you can run compiler dynamically from Java using the Java Compiler API. After compilation you can load the class and instantiate it or do whatever you want.

Here is also some old tutorial how to do this.

Upvotes: 3

ruakh
ruakh

Reputation: 183321

You never actually compile the class; you're trying to load Java source-code (*.java) as though it were a class-file (*.class).

To solve this, you will need to invoke a Java compiler at some point in the process. The easiest is simply to compile the program beforehand, and put the class-file on your web-site instead of (or in addition to) the source-code.

Upvotes: 3

Pradeep Pati
Pradeep Pati

Reputation: 5919

You aren't getting the real java class in the InputStream, that is why the code is throwing error. Try logging the input you are receiving from the URL, that would tell you whats wrong.

Also look at this question, he faces the same issue as you.

Upvotes: 1

Related Questions