Solved

Using Introspection in Java

Posted on 2001-07-31
9
590 Views
Last Modified: 2012-06-27
Hi!

I'm developing some java application in conjunction with other parties.
One of them send me a class "package" that I have to integrate with ours using introspection. The problem is that I don't quite understand how.
Can someone explain to me, as simplified as possible, what is introspection and how to use it for integration. I know that has something to do with JavaBeans.
Also can someone point to me some good documentation about this issue.
Thanks,
0
Comment
Question by:jmsr
  • 6
  • 3
9 Comments
 
LVL 4

Expert Comment

by:sdussinger
ID: 6339016
Basically, introspection (or reflection as its called in the Java world) is the ability to inspect the fields and methods of a class at runtime. For example, one could load a class into the JVM, determine the names and argument lists for methods within that class, and call them. Without any previous knowledge of the class's contents.

A couple of good starting articles on reflection:
http://www.javaworld.com/javaworld/jw-08-1997/jw-08-indepth.html
http://www.javaworld.com/javaworld/jw-09-1997/jw-09-indepth.html

A few more of interest:
http://developer.java.sun.com/developer/technicalArticles/ALT/Reflection/
http://java.sun.com/products/jdk/1.1/docs/guide/reflection/

My guess is that your initial task will be to load the class and write some reflection code which will dump the methods and fields of the class you wish to integrate. From there, you can determine what parameters are needed to call the methods, and can integrate those calls into your existing code.

HTH.

--Steve
0
 
LVL 4

Expert Comment

by:sdussinger
ID: 6339031
Some code might be in order here:

First, we load a class and print out its public fields, member methods, and constructors:

public void dumpInfo (String className) throws ClassNotFoundException, SecurityException
{
  Class c = Class.forName (className);

  System.out.println ("Public Fields:");

  Field f[] = c.getDeclaredFields ();

  for (int i = 0; i < f.length; i++)
    System.out.println (f[i].toString ());

  System.out.println ("");
  System.out.println ("Public Constructors:");

  Constructor cons[] = c.getDeclaredConstructors ();

  for (int j = 0; j < cons.length; j++)
    System.out.println (cons[j].toString ());

  System.out.println ("");
  System.out.println ("Public Methods:");

  Method m[] = c.getDeclaredMethods ();

  for (int k = 0; k < m.length; k++)
    System.out.println (m[k].toString ());
}

--Steve
0
 
LVL 4

Expert Comment

by:sdussinger
ID: 6339041
Once you have a listing of the possible fields, methods, and constructors. You need to be able to do something with them.  Here we call a method on a class which we've loaded.

public void callMethod () throws ClassNotFoundException, SecurityException
{
  Class c = Class.forName ("pkg.myClass");

  try
  {
    // Find a method called "methodToCall" Which takes 1 single string as a parameter.
    // If the method with the correct arg list is not found, then throw a NoSuchMethodException
    Method m = c.getMethod ("methodToCall", new Object [] { String.getClass () } );

    // Got the correct method, so create an arg list with the
    // string Hello in it, and call the method. If the
    // method returns a value it will be in val.
    Object val = m.invoke (new Object [] { new String ("Hello") } );
  }
  catch (NoSuchMethodException nsme)
  {
    nsme.printStackTrace ();
  }
}

--Steve
0
 
LVL 4

Accepted Solution

by:
sdussinger earned 300 total points
ID: 6339053
Oops. The last one should read like this. THat's what happens when you're in a hurry :-).

public void callMethod () throws ClassNotFoundException, SecurityException
{
 Class c = Class.forName ("pkg.myClass");

 try
 {
   // Find a method called "methodToCall" Which takes 1 single string as a parameter.
   // If the method with the correct arg list is not found, then throw a NoSuchMethodException
   Method m = c.getMethod ("methodToCall", new Object [] { String.getClass () } );

   // Create an instance of myClass to call the method on...
   // This assumes that myClass has a default constructor.
   Object aMyClass = c.newInstance ();

   // Got the correct method, so create an arg list with the
   // string Hello in it, and call the method. If the
   // method returns a value it will be in val.
   Object val = m.invoke (aMyClass, new Object [] { new String ("Hello") } );
 }
 catch (NoSuchMethodException nsme)
 {
   nsme.printStackTrace ();
 }
}

Sorry for the confusion.

--Steve
0
What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

 

Author Comment

by:jmsr
ID: 6355369
Sorry for not get back to you, sdussinger, but I've been very busy.
Ok. So I now know how to introspect a class. Thanks a lot, I will give you the answer points. I actually made some tests an I could get fields and methods from a given Class. I just allways need to know in advance the names of the fields and methods. Right?

But now I have another problem concerning this. Now I need to "construct" this class and load it in RunTime so I can use it within my application. The thing is: I'm getting all that information by using rmi from a, let's say, class description catallogue. I have the class description the fields, the methods, the parameters their type and return type. All this in alias form (Srings). Now I have to build a class with this information and then load it to my environment.

Any suggestions in how would I be able to achieve this?

I was taking a look to ClassLoader but this uses a stream of bytes as input and that's not what I have.

Please give me some hints on this or from where should I start.
Thanks a lot. Regards.

Jo?o
0
 
LVL 4

Expert Comment

by:sdussinger
ID: 6355847
1) You don't need to know the names of the fields or methods in advance. You can look up the names of fields and methods using the code I posted earlier. All you need to do is load the class (using Class.forName()) and call getFields, getMethods, or getConstructors to find the names. After that, you can access them.

2) Are you talking about actually dynamically creating the bytecode for classes at runtime? Or do you already have a class and just want to load it?

--Steve
0
 

Author Comment

by:jmsr
ID: 6355903
Yap. Actually I'm talking about creating the bytecode for the classes and then load them. That's what is making this quite dificult.
The only thing I've got is classes (that I have to introspect) with the descriptions of the classes I really need. A bunch of Strings with the name, fields, methods, parameter and types.
No I need to create the class, probably compile it, and then load it. Pretty scary! At least for me! :-(
If you can help me with this, please do. If not please just explain me how to load the classes in RunTime and I will try to figure out the first part.
Thanks,

Joao
0
 

Author Comment

by:jmsr
ID: 6356291
Yap. Actually I'm talking about creating the bytecode for the classes and then load them. That's what is making this quite dificult.
The only thing I've got is classes (that I have to introspect) with the descriptions of the classes I really need. A bunch of Strings with the name, fields, methods, parameter and types.
No I need to create the class, probably compile it, and then load it. Pretty scary! At least for me! :-(
If you can help me with this, please do. If not please just explain me how to load the classes in RunTime and I will try to figure out the first part.
Thanks,

Joao
0
 
LVL 4

Expert Comment

by:sdussinger
ID: 6358081
Ok, let's start with the easier of the two: loading the class file once you've created it.

Assuming that the .class files are in a directory on your local machine called "dynamicClasses", you could write a function like this to load them:

import java.net.URLClassLoader;

Class loadClass (String className)
{
  URLClassLoader cl = null;

  try
  {
    cl = URLClassLoader.newInstance (new URL []
                                           {
                                             new URL ("file:/dynamicClasses"),
                                           } );

      Class c = urlcl.loadClass (className);

      return (c);
    }
    catch (Exception e)
    {
      e.printStackTrace ();
    }
  }

  return (null);
}

This will handle loading a class from the location you specified. Notice that the URLClassLoader constructor takes an array of URLS, so you can contruct an array of locations for the loader to try to find your class.

Now for the hard part, generating bytecodes:

Are you going to be generating source code and then building the bytecodes from that or do you want to build bytecodes from scratch (effectively builing your own bytecode assembler)?

If you have the source code (or can generate it) for a Java class, you can call the Sun compiler directly from inside your program.

The following code will do that for you:

public class CompTest
{

  public static void main (String args[])
  {
    sun.tools.javac.Main compiler = new sun.tools.javac.Main (System.out, "javac");

    String params[] = new String[] { "test.java" };

    if (compiler.compile (params) == true)
      System.out.println ("Compile succeeded");
    else
      System.out.println ("Compile failed");
  }

}

This will compile the file test.java and create a class file called test.class. You can load the test.class file using the URLClassLoader code above.

If, pn the other hand, you want to generate the actuall byte codes yourself, take a look at the IBM alphaWorks JIKES Bytecode library. The url is: http://alphaworks.ibm.com/aw.nsf/techmain/jikesbt

Hope this helps...

--Steve
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now