6

I have some class A:

public class A {
 public A(String str) {
 System.out.println("Create A instance: " + str);
 }
 public void methodA() {
 System.out.println("#methodA1()");
 }
}

And my class loader implementation:

public class MyClassLoader extends ClassLoader {
 public MyClassLoader() { 
 super();
 }
 @Override
 public synchronized Class<?> loadClass(String name) 
 throws ClassNotFoundException {
 System.out.println("Load: " + name);
 return super.loadClass(name);
 }
}

And now I try to change default class loader in current thread:

import java.util.ArrayList;
import java.util.List;
public class ChangeLoaderTest {
 public static void main(String[] args) {
 // Save class loader so that we can restore later.
 ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
 MyClassLoader newLoader = new MyClassLoader();
 try {
 // Set new classloader.
 Thread.currentThread().setContextClassLoader(newLoader);
 // My class.
 A a = new A("1");
 a.methodA();
 // Standard Java class.
 List<Integer> list = new ArrayList<Integer>();
 list.add(2);
 list.add(3);
 } finally {
 // Restore.
 Thread.currentThread().setContextClassLoader(oldLoader);
 }
 }
}

And ChangeLoaderTest output:

Create A instance: 1
#methodA1()

No one

Load: ...

Why? How I can change ClassLoader into some thread?

asked Apr 17, 2012 at 13:42
2
  • "I have some class A:" While some people think it is better to 'abstract a problem' to the point you can express it as obtuse symbols, I prefer some context that helps explain what is in class A that makes you want to load it dynamically. I.E. class A might be a UserDefinedPlugIn - the latter provides some context, the former does not. Commented Apr 17, 2012 at 13:48
  • Ok, I can explain context of this question. I have class that reads images into BufferedImage. Sometimes it is ImageIO.read(file), sometimes it is Sanselan.getBufferedImage(file). I have my own class for saving images and I should create BuffredImage from file, then copy data from BufferedImage to my object. I want using some proxy class to catch all #get(...) methods call to save information in my object. Commented Apr 17, 2012 at 17:32

3 Answers 3

4

As Marko Topolnik points out the context classloader is for use by frameworks. To use the classloader yourself you have to call loadClass("somepackage.A") and then use the reflection API to create a new instance of A (Class.newInstance()).

You wont be able to use A or its methods in your source directly since the calling code does not know A - it uses a different classloader. An interface or baseclass of A that can be loaded by the normal classloader can be used to avoid reflection.

interface AIF{
 void someMethod();
 }
class A implements AIF{
 public void someMethod(){}
 }
public void test(){
 MyLoader loader = new MyLoader();
 Class cla = loader.loadClass("A");
 AIF a = (AIF) cla.newInstance();
 a.someMethod();
 }
answered Apr 17, 2012 at 14:23
Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately, you can't define a non-default constructor in an interface (any constructor for that matter) the way vanveber has it. So, entre reflection...
@mazaneicha you could bypass that by creating factory class and a factory interface (only if you really hate reflection).
3

The contextClassLoader mechanisms is not used by the basic Java operations like new. It's only there so various frameworks can access the context class loader in charge and load resources, classes, etc. Java will always use the classloader that loaded the code that is executing. It's the one that you access via ChangeLoaderTest.class.getClassLoader() -- and there is nothing you can do about this one.

answered Apr 17, 2012 at 13:58

Comments

0

I think that what happens is that your application's class loader which is also your classloader's "parent" can locate A and load it. As a result your classloader will not be searched or used for loading A.

To be honest, I haven't much experience with classloaders but if you subclassed one that uses a URL for the path of the class (so that it can locate the class file) and the parent classloader can not load it (not part of classpath), your custom one will be used.

answered Apr 17, 2012 at 13:58

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.