Go Back   Velocity Reviews > Newsgroups > Java
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply

Java - What is the difference between Class.forName and ClassLoader.defineClass

 
Thread Tools Search this Thread
Old 12-06-2005, 04:30 PM   #1
Default What is the difference between Class.forName and ClassLoader.defineClass


Dear all,

I have three ways of reading in a class in a dynamic way: Instantiating
the class works with two of them, with the third this results in an
exception:

Exception in thread "main" java.lang.IllegalAccessError: tried to
access class JSHOP2_Method0 from class domainpresentationplanner

>From the class description, I cannot find out why defineClass does not

work. The three ways are:

// (1) does not work
File file = new File(full_path_to_file,
"domainpresentationplanner.class");
classCode = getBytesFromFile(file);
domainClass = defineClass("domainpresentationplanner", classCode, 0,
classCode.length);
domain = (Domain) domainClass.newInstance(); // the same in all three
cases

// (2) works
domainClass = loadClass("domainpresentationplanner");
domain = (Domain) domainClass.newInstance();

// (3) works
domainClass = Class.forName("domainpresentationplanner");
domain = (Domain) domainClass.newInstance();


getBytesFromFile is taken from
http://javaalmanac.com/egs/java.io/File2ByteArray.html

I should mention that domainpresentationplanner.java, the java file
whose compilation produced domainpresentation.class, is comprised of
several classes, one of them being JSHOP2_Method0. All resulting class
files are in the same directory as domainpresentation.class.

Why does version (1) not work but (2) and (3) do?

Thank you, Uli



Ulrich Scholz
  Reply With Quote
Old 12-06-2005, 05:16 PM   #2
oulan bator
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

Hi,

defineClass is protected, then that means that your are overriding a
ClassLoader.
check then for the findClass() method (log calls)

I don't known if this is a "simplified" version of your code, but
that's not the usual way to dynamically load classes using define class

BR

  Reply With Quote
Old 12-06-2005, 05:36 PM   #3
Thomas Fritsch
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

Ulrich Scholz schrieb:
> I have three ways of reading in a class in a dynamic way: Instantiating
> the class works with two of them, with the third this results in an
> exception:
>
> Exception in thread "main" java.lang.IllegalAccessError: tried to
> access class JSHOP2_Method0 from class domainpresentationplanner
>
>>From the class description, I cannot find out why defineClass does not

> work. The three ways are:
>
> // (1) does not work
> File file = new File(full_path_to_file,
> "domainpresentationplanner.class");
> classCode = getBytesFromFile(file);
> domainClass = defineClass("domainpresentationplanner", classCode, 0,
> classCode.length);
> domain = (Domain) domainClass.newInstance(); // the same in all three
> cases

As described in
<http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ClassLoader.html> all
the defineClass(...) methods are all declared protected. As such they
can only be called from *within* ClassLoader and its subclasses.
You would need to fiddle with defineClass(...) *only* if you write your
own subclass of ClassLoader. You never call defineClass(...) from
outside, but instead let it be called from inside the ClassLoader base
class.
>
> // (2) works
> domainClass = loadClass("domainpresentationplanner");
> domain = (Domain) domainClass.newInstance();

As described in
<http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ClassLoader.html#loadClass(java.lang.String)>
ClassLoader's method loadClass(String) is called by the JVM to load
classes. Therefore I think it is not meant to be used by applications
(at least not by "normal" applications). Don't ask me why it is public,
though. private would have been enough, because the JVM is able to call
even private methods.
>
> // (3) works
> domainClass = Class.forName("domainpresentationplanner");
> domain = (Domain) domainClass.newInstance();

Class.forName(String) and Class.forName(String,boolean,ClassLoader) is
the most high-level method of your 3 ways, and therefore the most usual
way to load classes. I would recommend to restrict your application to
use only Class.forName, and try to avoid explicit calls to ClassLoader
methods as much as you can.
BTW: Class.forName(...) and newInstance() only work if the class is
public and has a public no-argument constructor.
>
>
> getBytesFromFile is taken from
> http://javaalmanac.com/egs/java.io/File2ByteArray.html
>
> I should mention that domainpresentationplanner.java, the java file
> whose compilation produced domainpresentation.class, is comprised of
> several classes, one of them being JSHOP2_Method0. All resulting class
> files are in the same directory as domainpresentation.class.
>
> Why does version (1) not work but (2) and (3) do?


--
"Thomas:Fritsch$ops:de".replace(':','.').replace(' $','@')
  Reply With Quote
Old 12-06-2005, 06:26 PM   #4
Ulrich Scholz
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

> As described in
> <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ClassLoader.html#lo...)>
> ClassLoader's method loadClass(String) is called by the JVM to load
> classes.


I should have mentioned that I did try the three ways in a subclass of
ClassLoader.

  Reply With Quote
Old 12-06-2005, 07:36 PM   #5
Roedy Green
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

On 6 Dec 2005 08:30:56 -0800, "Ulrich Scholz" <> wrote,
quoted or indirectly quoted someone who said :

> domainClass = defineClass("domainpresentationplanner", classCode, 0,
>classCode.length);

I gather this code is hidden inside your own classloader? But you
hard coded a name? I think we need to see more of your program to
figure out what you did.
--
Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.
  Reply With Quote
Old 12-07-2005, 12:52 AM   #6
Chris Smith
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

Ulrich Scholz <> wrote:
> > As described in
> > <http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ClassLoader.html#lo...)>
> > ClassLoader's method loadClass(String) is called by the JVM to load
> > classes.

>
> I should have mentioned that I did try the three ways in a subclass of
> ClassLoader.


Okay. The difference, then, is that Class.forName and
ClassLoader.loadClass both use the normal class loading scheme.
ClassLoader.defineClass skips that normal scheme and defines the class
directly in this class loader.

The normal scheme is to do the following:

1. First, ask the parent class loader for the class.
2. If the parent doesn't have it, load it in this class loader.
3. If this class loader can't find it, throw an exception.

So if you're seeing the behavior you describe, it must be because
Class.forName and ClassLoader.loadClass are actually finding the class
in the parent. However, defineClass doesn't look in the parent first,
so it loads the class in the current class loader.

So why does this cause IllegalAccessError? You're attempting to access
a package-access class from its package. However, when your class
domainpresentationplanner uses that other class, the other class *is*
loaded by the default scheme described above, and ends up loaded from
the parent class loader. So you end up with domainpresentationplanner
loaded from one class loader, and JSHOP2_Method0 loaded from a different
class loader. Even though their packages have the same name, a package
can belong to one and only one class loader... so they are actually
different packages. The package-access level doesn't permit this, and
the error is thrown.

Confused? You should be. Basically, you should never call defineClass
in a class loader except in the following circumstances:

A. You may call defineClass from findClass, if you are writing a class
loader that respects the delegation model.

B. You may call defineClass from loadClass(String,boolean) if you are
writing a class loader that does *not* respect the delegation model.

However, you *must* use delegation consistently throughout your class
loader. Pick A or B, not both (and implement B consistently, if that's
your choice).

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
  Reply With Quote
Old 12-07-2005, 11:37 AM   #7
Hendrik Maryns
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

Roedy Green schreef:
> On 6 Dec 2005 08:30:56 -0800, "Ulrich Scholz" <> wrote,
> quoted or indirectly quoted someone who said :
>
>
>>domainClass = defineClass("domainpresentationplanner", classCode, 0,
>>classCode.length);

>
> I gather this code is hidden inside your own classloader? But you
> hard coded a name? I think we need to see more of your program to
> figure out what you did.


And how about starting class names with an uppercase letter?

H.

--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
  Reply With Quote
Old 12-07-2005, 12:17 PM   #8
Chris Uppal
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

Ulrich Scholz wrote:

> // (1) does not work
> File file = new File(full_path_to_file,
> "domainpresentationplanner.class");
> classCode = getBytesFromFile(file);
> domainClass = defineClass("domainpresentationplanner", classCode, 0,
> classCode.length);
> domain = (Domain) domainClass.newInstance(); // the same in all three
> cases


[This is only emphasing a point made in the other replies]

You should not use defineClass() to create class objects /except/ as one
private step in the overall process of loading a class (as controlled by the
JVM). Application code should never create a class object that way, it should
always use one of the forms of Class.forName().

-- chris


  Reply With Quote
Old 12-07-2005, 02:42 PM   #9
Ulrich Scholz
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

> Application code should never create a class object [with defineClass()],

OK, I agree

> it should always use one of the forms of Class.forName().


Here, I have my doubts. From my current (in the last two day constantly
growing) knowledge about the class loading mechanism of Java (or, at
least what I believe to know about it), it follows that I have to
create new subclasses of ClassLoader because I dynamically create and
use a class file of the same name. For each new version I need a
different ClassLoader.

As I need to write a sublcass of MyClassLoader ClassLoader anyway,
where's the difference of using Class.forName/3 with an instance of
MyClassLoader and of using MyClassLoader.loadClass/2 directly?

Uli

  Reply With Quote
Old 12-07-2005, 03:04 PM   #10
Chris Uppal
 
Posts: n/a
Default Re: What is the difference between Class.forName and ClassLoader.defineClass

Ulrich Scholz wrote:

> As I need to write a sublcass of MyClassLoader ClassLoader anyway,
> where's the difference of using Class.forName/3 with an instance of
> MyClassLoader and of using MyClassLoader.loadClass/2 directly?


Calling loadClass() directly side-steps some of the stuff that the JVM does
with the new class after it has been loaded and before it is returned by
Class.forName(). E.g. try getting the class object for MyClass[];
Class.forName("[LMyClass;", true, aClassloader)
works (or whatever the exact String should be -- I can't remember off-hand) but
trying the same thing via a classloader does not, since it is the JVM that
"manages" array classes. There /may/ be other processing that it side-steps
too, I don't know for sure, and the specs are not clear.

-- chris


  Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump