performance of Class.forname()?

A

Ahmed Moustafa

In a couple of performance articles, it is recommended to dynamically
load classes as needed with Class.forname().

Why?
 
R

Roedy Green

In a couple of performance articles, it is recommended to dynamically
load classes as needed with Class.forname().

I can't think of a performance reason.

Java does not load classes until they are needed, whether or not you
use Class.forName.

The usual reason for using it is to allow plugin classes that are
created later.

For example, I use them in my HTMLMacro skeleton. You can add new
Macros written in Java without recompiling the macro expansion shell
engine.

I also use them in the Holiday Calculator. You can add more holidays
just by implementing an interface.

In static native compilation, Class.forName screws things up. New
classes come in out of the blue that were not present for global
optimisation at compile time.
 
A

Ahmed Moustafa

Lothar said:
There should be a reason in the articles. IMHO it's better to
initialize instances the "normal" way (using new) to be able
to find errors during compile-time. A

MyClass myClass = Class.forName("Myclass");

will lead to a ClassNotFoundException during runtime. A

MyCLass myClass = new Myclass()

allows the compiler to tell you that there is no class with
name Myclass.

And I'm quite sure that you will lose more time in a
constructor being implemented inefficently that you
will get with using forName instead of new.

Do you have a link to one of these "couple of" articles?

http://www.cs.utexas.edu/users/toktb/J-Breeze/javaperform.tips.html#classes
http://patrick.net/jpt/
 
R

Roedy Green


states:

"Unless a method is final, it is located on demand at runtime. Methods
are encoded in .class files as strings, not addresses. This allows
them to be relocated easily and makes overflow attacks harder, since
you don't know where any particular method is going to be. But this
also means a lot of runtime overhead of string parsing and method
location is going on at runtime, unlike C, where execution jumps
directly to the address compiled into the code."

This is misleading. It gives the impression that methods are linked
with some sort of hashtable on every call. Even in the most primitive
interpreted systems, methods links are converted to direct address
links on first call. This is partly why you can't easily replace class
files on the fly.
 
R

Roedy Green


I think the explanation is that "Patrick" has gleaned his knowledge by
pragramatic experiments and made some guesses as to how the JVM worked
inside, but did not check to see if he was correct. I think He
imagines that Class.forName will save RAM. He probably thinks that
all classes in the jar are loaded, whether they are used or not by the
ordinary mechanism.
 
A

Adam Maass

Ahmed Moustafa said:
In a couple of performance articles, it is recommended to dynamically
load classes as needed with Class.forname().

Why?

Under normal operation, the JVM does not load classes into main memory until
they are needed, often in response to a call to the new operator. Delaying
class loading like this may result in a slowdown as the needed classes are
loaded (but only the first time they are needed).

I am guessing that the articles (without any references) say that using
Class.forName on the classes may avoid the dynamic loading that happens the
first time they are needed.


While this is true, I wouldn't recommend it unless you can prove two things:

1) Dynamicly loading classes as they are needed results in an unacceptable
slowdown,
2) Forcing the classes to load before they are needed with Class.forName
actually makes things better.

I wager that this is a tough test to meet. In my experience, many classes
are loaded long before I naively expect them to be: this is because the JVM
traces static class references in the entire class file as it is being
loaded and recursively loads all of the classes needed to resolve the
symbols. Additionally, the strategy of forcing classes to load with
Class.forName works only when there is a long delay between the time the
forced-load happens (often at startup) and the time the classes are actually
needed. The strategy is fragile: it relies on some list of classes that need
to be pre-loaded; that list needst to be generated and maintained if it is
to be of any use. And since the GC can unload classes if they don't have any
instances or active threads in any method, the strategy is likely to fail to
achieve its purpose anyway.


-- Adam Maass
 
M

Mark Thornton

Adam said:
I wager that this is a tough test to meet. In my experience, many classes
are loaded long before I naively expect them to be: this is because the JVM
traces static class references in the entire class file as it is being
loaded and recursively loads all of the classes needed to resolve the
symbols. Additionally, the strategy of forcing classes to load with
Class.forName works only when there is a long delay between the time the
forced-load happens (often at startup) and the time the classes are actually
needed. The strategy is fragile: it relies on some list of classes that need
to be pre-loaded; that list needst to be generated and maintained if it is
to be of any use. And since the GC can unload classes if they don't have any
instances or active threads in any method, the strategy is likely to fail to
achieve its purpose anyway.

The GC can only unload classes where the classloader for a class is
unreachable. This is a change from the early Java releases where GC did
unload individual classes. This was changed to avoid surprises from
changes in static fields (returning to their initial state).

Mark Thornton
 
P

pete kirkham

http://www.cs.utexas.edu/users/toktb/J-Breeze/javaperform.tips.html#classes

includes:
Classes/Interface
* replace generic standard classes with faster implementations specific to application
* create subclasses to override methods with faster versions
* program using interfaces, so that actual structure can be easily swapped to improve performance ....
* dynamically load class with Class.forname() (why? no reason given)

'No reason given'- but how else do you do the first three dynamically?
String

* use char[] array directly to create String rather than StringBuffer
* convert string to char[] to process character, rather than using charAt()
Both require an array copy.

for (int k=0; k<10000; k++) {
for (int j=0; j<strings.length; j++) {
// converting to char array >>>>>
char[] data = strings[j].toCharArray();
for (int l=0; l<data.length; l++) {
really = really && data[l] == 'j';
}
}
}
runs in around 17ms where strings is an array of ten Strings of length 7.

for (int i=0; i<10; i++) {
start_time = System.currentTimeMillis();
for (int k=0; k<10000; k++) {
for (int j=0; j<strings.length; j++) {
String data = strings[j];
for (int l=0; l<data.length(); l++) {
// calling charAt >>>>>
really = really && data.charAt(l) == 'j';
}
}
}
runs in around 5ms with the same data (java 1.4.1_01-39 on OS X)


Pete
 
J

Jon A. Cruz

pete said:
'No reason given'- but how else do you do the first three dynamically?

Hmmm... let me jump in here with no context and just try to hack some
answer...

OK. The first one is easy.

Document myDoc = new MyTunedForMyAppDoc();
JTextArea area = new JTextArea( myDoc );

Bingo!
:)

Or
Document myDoc = new MyStupidButOnly16KDoc();

etc.

* the second:
Basically the same thing

Gee. And same on the third.


All three of those can be implemented through several standard patterns,
including factory methods and singletons. No class.forName() required.



runs in around 17ms where strings is an array of ten Strings of length 7.
runs in around 5ms with the same data (java 1.4.1_01-39 on OS X)

So the "optimized" version is more than 3 times slower on your machine?
 
C

Chris

Jon Skeet said:
Out of interest, which VM was that with? It'd be interesting to see the
results on various VMs, as I believe 1.4 is significantly faster at
this than 1.3.1.

This was on 1.3.1, but I've just installed 1.4.2 and will be
re-compiling this evening, I've still got the alternative code so I'll
post the results tomorrow.

- sarge
 
P

Peter McDonnell

"I substituted a factory class for the dynamic loader and got a 100%
increase in the parsing part of the descriptor loader."

Not sure what you're measuring here. If you don't include the time taken to
statically load the referenced classes (presumeably as part of the
class-loading of the parser itself), then you are only comparing dynamically
loading classes vs having them loaded already, which isn't really a fair
comparison.

As mentioned earlier the time taken to statically load the classes may
appear much earlier in your program load time, but will still count against
overall performance.

You could try pre-loading the Class objects into a Map before you started
parsing and get a better comparison over the newInstance() vs new Classname
performance though. Otherwise I think you'd have to measure the performance
gain over the whole run-time of the program (or at least up until the
parsing has completed) to get a more accurate static vs dynamic loading
comparison.

Regards,
Peter
 
P

pete kirkham

Jon said:
Hmmm... let me jump in here with no context and just try to hack some
answer...

OK. The first one is easy.

Document myDoc = new MyTunedForMyAppDoc();
JTextArea area = new JTextArea( myDoc ); ....
Or
Document myDoc = new MyStupidButOnly16KDoc();

Is this dynamic? In this you have replaced the implementation of
Document using a statically linked class. Can the client of your code
choose to replace your implementation of Document with one tuned for
_their_ specific application, or are they stuck with your solution based
on _your_ assumptions as to what to optimise? If this is part a library,
have you enabled the client to apply the three optimisation techniques
listed?
All three of those can be implemented through several standard patterns,
including factory methods and singletons. No class.forName() required.

How do you implement these patterns dynamically, by which I mean
allowing the client to replace the default implementation with one
optimised for their application, without using Class.forName() (or
hacking bytecode/calling the compiler etc.)?
So the "optimized" version is more than 3 times slower on your machine?

That indeed was the point. Trust the profiler, not the mythology.


Pete
 
J

Jon A. Cruz

pete said:
Is this dynamic? In this you have replaced the implementation of
Document using a statically linked class. Can the client of your code
choose to replace your implementation of Document with one tuned for
_their_ specific application, or are they stuck with your solution based
on _your_ assumptions as to what to optimise? If this is part a library,
have you enabled the client to apply the three optimisation techniques
listed?

Sorry. That's what I get for posting when too tired.

You can use those to hide the Class.forName().

One good example is how to get a SAX parser.

That indeed was the point. Trust the profiler, not the mythology.

And remember, it might differ on each system. What you do to help on one
can hurt on another.
 
D

dhek bhun kho

Hello Ahmed

In a couple of performance articles, it is recommended to dynamically
load classes as needed with Class.forname().

Why?

It's very dependent on a lot of factors, just like most of the other
optimisations. There aren't many hard and fast rules. For one thing, I
would not trust an article that is date around the release data of java
1.2. There have been a lot of changes in the JVM itself since then.

The Class.forName() argument probably holds for the user, when several
things like 1) The application code is HUGE, and 2) The code is loaded over
the network, are true.

If the code base is huge, and you start a program, you must remember that
you have a programmed a big class tree. So when you load the first class,
the class loader will try to load all classes referenced by the first call
and link them.

If everything is linked statically, then the JVM will load
and link every single class of your program before your application even
starts. That can be perceived as a huge performance hit, because the
application takes longer to start. (I'm almost sure this is the case with
Swing applets).

If you can divide the application in several parts where
certain parts are started by an object that is instantiated by a class
loaded with Class.forName, everything starting at that class is not loaded
until the code actually executes the Class.forName call. Combine that fact
with low-speed connections and you have to wait a long time. There may be
other issues that aren't so apparent.

Greets
Bhun.
 
C

Chris Smith

Jon said:
Sorry. That's what I get for posting when too tired.

You can use those to hide the Class.forName().

One good example is how to get a SAX parser.

No, no, no! Jon, you were right before. Class.forName is not required
to provide flexibility to clients in tuning performance. In fact, a far
better way to do this in the general case is to define interfaces and
let clients specify the correct behavior in code by providing an
implementation of that interface. If new objects need to be created,
passing in factory interfaces can do the trick.

Class.forName comes in when you want to be able to modify the
configuration of an application without making code changes. That's
really a somewhat rare need; it's usefulness has largely been
manufactured by Sun. By definition in the case cited above, it's a Java
programmer that wrote that code, and it's a Java programmer that wants
to use it, so the link can be made in Java, just as easily as in some
properties file in a META-INF directory.

I've long had this vision of Sun sitting around thinking "what does Java
have that other popular languages don't? Oh, reflection! Let's start
pushing it like it's the solution to all the world's problems!", and so
was the nightmare of J2EE born. It's rather unfortunate -- nay, tragic
-- that this has now spread into J2SE classes like a hideous cancer!

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

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,829
Latest member
PIXThurman

Latest Threads

Top