loading class with a different name

  • Thread starter Francesco Devittori
  • Start date
F

Francesco Devittori

Hi all,
I want to write a specialized classLoader that loads a class under a
different name.

For example, it should load the bytecode of "java.util.ArrayList" and
provide the class MyArrayList instead of ArrayList. The bytecode of
MyArrayList should be the same as the one of ArrayList (i.e. objects of
the two classes work the same way).
That way I could end up with objects of type ArrayList and objects of
MyArrayList, which work the same way but are not "compatible".

Do someone with some experience with classLoaders thinks this is
possible? If yes, how difficult would it be?

TIA,
Francesco
 
S

Stefan Ram

Francesco Devittori said:
Do someone with some experience with classLoaders thinks this
is possible? If yes, how difficult would it be?

I have nearly no knowledge about class loaders and nearly no
experience with tem, but recently I hacked together something
like this. - Not exactly the same as you require: It does
not use two names, but two class loaders.

Beware! The following example does not follow style rules for
writing good class loaders!

I wanted to show how to create two "instances" of a class with
static entries:

public class Scan { static int i = 0; public static int get(){ return i++; }}

So here I go, creating two "instances":

public class Main
{ public static void main( java.lang.String[] args ) throws java.lang.Exception
{ final java.lang.Class instance1 = new ScanLoader().loadClass( "Scan" );
final java.lang.Class instance2 = new ScanLoader().loadClass( "Scan" );
final java.lang.Class[] c = new java.lang.Class[]{};
final java.lang.Object[] o = new java.lang.Object[]{};
java.lang.System.out.println( instance1.getMethod( "get", c ).invoke( null, o ));
java.lang.System.out.println( instance1.getMethod( "get", c ).invoke( null, o ));
java.lang.System.out.println( instance2.getMethod( "get", c ).invoke( null, o ));
java.lang.System.out.println( instance2.getMethod( "get", c ).invoke( null, o )); }}

They can count indepently of each other, as the
output shows:

0
1
0
1

And here is my custom class loader hack:

class ScanLoader extends ClassLoader
{ public ScanLoader()
{ super( ScanLoader.class.getClassLoader() ); }
public java.lang.Class<?> loadClass( final java.lang.String className )
throws ClassNotFoundException
{ return findClass( className ); }
public java.lang.Class<?> findClass( final java.lang.String className )
{ byte classByte[];
java.lang.Class<?> result = null;
if( "java.lang.Object".equals( className ))return java.lang.Object.class;
try
{ java.lang.String classPath =
(( java.lang.String )ClassLoader.getSystemResource
( className.replace( '.', java.io.File.separatorChar ) + ".class" ).getFile() ).
substring( 1 );
classByte = loadClassData( classPath );
result = defineClass( className, classByte, 0, classByte.length, null );
return result; }
catch( final java.lang.Exception e ){ throw new java.lang.RuntimeException(e); }}
private byte[] loadClassData
( final java.lang.String className )
throws java.io.IOException
{ final java.io.File f = new java.io.File( className );
final int size =( int )f.length();
final byte buff[] = new byte[ size ];
{ java.io.FileInputStream fis = new java.io.FileInputStream( f );
{ java.io.DataInputStream dis = new java.io.DataInputStream( fis );
dis.readFully( buff );
dis.close(); }}
return buff; }}
 
F

Francesco Devittori

Stefan said:
I have nearly no knowledge about class loaders and nearly no
experience with tem, but recently I hacked together something
like this. - Not exactly the same as you require: It does
not use two names, but two class loaders.

Beware! The following example does not follow style rules for
writing good class loaders!

Very nice, thanks. This is enough for what I want to do.
However I am realizing that a custom classLoader cannot load classes
with names starting with "java.lang".
Is this true?

(another question: why do you do substring(1) in your implementation?)

Francesco
 
C

Chris Uppal

Francesco said:
Hi all,
I want to write a specialized classLoader that loads a class under a
different name.

IIRC the JVM will not allow you to load a class under any name except that
which is embedded in the classfile definition. Therefore you would have to
decode and re-encode the classfile (not impossible, not even all that
difficult, but you'll need something like the ASM library or BCEL).

-- chris
 
S

Stefan Ram

Francesco Devittori said:
Very nice, thanks. This is enough for what I want to do.
However I am realizing that a custom classLoader cannot load
classes with names starting with "java.lang".
Is this true?

I am not aware of such a restriction, but then, as I said,
I have no clue about class loaders, except that I hacked
together the declaration of the class "ScanLoader".
(another question: why do you do substring(1) in your implementation?)

This removes a disturbing initial character,
I believe a slash "/".
 
T

Thomas Hawtin

Francesco said:
However I am realizing that a custom classLoader cannot load classes
with names starting with "java.lang".

Or any qualified name starting with "java.". Presumably to avoid people
creating incompatible versions of Java. However, you can transform
classes with the instrumentation API (from 1.5).

Tom Hawtin
 
F

Francesco Devittori

Thomas said:
Or any qualified name starting with "java.". Presumably to avoid people
creating incompatible versions of Java. However, you can transform
classes with the instrumentation API (from 1.5).

Tom Hawtin

My problem is that I want to reload some classes to have them not
transformed by the instrumentation API...

Francesco
 

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

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top