Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my reflection loading weird classes?

I'm trying to play with reflection to see if I can get to a point where I'm able to type in a class name and my application will load that class and create an instance of it. After a few attempts I found I couldn't just stick a class name in Class.forName() without its package name, so I wound up trying to get a list of all available packages that have been loaded and trying to load the class I type in with each package name till it gets a hit.

This is what I've got so far:

BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    String s = "";
    do
    {
        ClassLoader clsldr = ClassLoader.getSystemClassLoader();
        Package[] pkgs = Package.getPackages();
        s = console.readLine();
        if(s.equals(":exit"))
        {
            System.exit(0);
        }
        boolean classFound = false;
        Object loadedClass = null;
        String classname = "";
        for (int i = 0; i < pkgs.length; i++) {
            Package package1 = pkgs[i];
            try
            {
                classname = package1.getName().replace('/', '.') + "." + s;
                clsldr.loadClass(classname);
                loadedClass = Class.forName(classname);
                classFound = true;
            }
            catch(Exception e)
            {

            }

        }
        System.out.println("LOADED A CLASS!!!!");
        System.out.println(classname);
        System.out.println(loadedClass);
    }
    while(s.length() == 0);

It semi works in a very weird way. For example when I type in "Object" at the prompt it somehow manages to load sun.net.util.Object, but when I print out the actual object it prints class java.lang.Object. I get the same thing with a String as well as several other things I typed. One interesting one I tried was int - it loaded sun.net.util.int and when I printed the object it just returned null. Another happened when I tried Java:

Java
LOADED A CLASS!!!!
sun.net.util.Java
null

Does anyone have any clue what's happening here? Is there something special about the sun.net.util package that's causing this? I don't really care that my code doesn't work exactly like I want, I would just love to know what's causing this strange behaviour.

Java version:

java version "1.7.0_25"                                         
Java(TM) SE Runtime Environment (build 1.7.0_25-b17)            
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode) 

I'm on Windows 8 64 bit if that makes any difference.

like image 734
ldam Avatar asked Aug 08 '13 22:08

ldam


People also ask

Is reflect slow?

Reflection is much more slower than compiled code. There is no discussion about that but compared with other trivial operations it is not that serious. Use reflection with care and measure its impact on your code performance, if you write time-critical part of your app.

What is reflection API in Java& why it is being used?

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.

How to implement reflection in Java?

In order to reflect a Java class, we first need to create an object of Class . And, using the object we can call various methods to get information about methods, fields, and constructors present in a class. class Dog {...} // create object of Class // to reflect the Dog class Class a = Class. forName("Dog");


1 Answers

Your code is returning "weird" classes because what it is doing is conceptually broken. There is nothing in any specification that says what the physical order of entries in the "rt.jar" file should be. They just happen to be in an order that results in you finding the "weird" one given the way you are doing the iteration. In another Java release, your code might give you the "non-weird" Object class. Either way, the assumption that you will get the "right" class this way is ... flawed.


You say that you are doing this because:

"I wanted to take a stab at making a Java interpreter"

Well if you are going to implement an interpreter, you need to understand the Java language. And one of the things that you need to understand is that there can be many classes with the same simple name in Java. This means that your idea of scanning the classpath for any class with a given simple name is simply not practical. You will find that there are too many "collision" (i.e. classes with the same simple name) for commonly used classes.

In conventional Java, this collision problem is addressed by either referring to classes by their fully qualified names or by importing them. For your interpreter to be usable, you need to implement an import scheme that mirrors conventional Java's import mechanism.

In short, ditch the code above and start again.

like image 122
Stephen C Avatar answered Nov 15 '22 00:11

Stephen C