shtern
asked on
new and newInstance
Hello!
I use a custom class loader for my application. The problem is: if I create an object somewhere in my app with a pair loadClass - newInstance, it's OK. If I do it with new, i become an error in defineClass function. The arguments are in both cases the same. Question: does not new do the same as loadClass - newInstance?
Thanx.
I use a custom class loader for my application. The problem is: if I create an object somewhere in my app with a pair loadClass - newInstance, it's OK. If I do it with new, i become an error in defineClass function. The arguments are in both cases the same. Question: does not new do the same as loadClass - newInstance?
Thanx.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
What kind of error do you get? If that's an exception, can you post stack trace?
Igor
Igor
ASKER
I think the problem is that somewhere in defineClass the normal ClassLoader is used. When I do it with loadClass - newInstance, I write like this:
Class cl = getClass().getClassLoader( ).loadClas s("HelloWo rld");
Object o = cl.newInstance();
This works. But if I use
HelloWorld h = new Helloworld();
it doesn't work.
Regards,
Olga Stern.
Class cl = getClass().getClassLoader(
Object o = cl.newInstance();
This works. But if I use
HelloWorld h = new Helloworld();
it doesn't work.
Regards,
Olga Stern.
ASKER
This is a ClassCircularityError. I try to replace the class HelloWorld with the class HelloworldWrap which extends HelloWorld. It seems like it would load Helloworld more than once or smth. like that.
Sounds like there's a problem with your HelloWorld class, can we see the code for it?
The fact that it works using one method and not using the other may possibly be a bug.
The fact that it works using one method and not using the other may possibly be a bug.
ASKER
It does practically nothing, just tells about it for test.
public class HelloWorld {
public HelloWorld() {
System.out.println("Constr uctor HelloWorld invoked");
}
}
public class HelloWorldWrap {
public HelloWorldWrap() {
System.out.println("Constr uctor HelloWorldWrap invoked");
}
}
Regards,
Olga.
public class HelloWorld {
public HelloWorld() {
System.out.println("Constr
}
}
public class HelloWorldWrap {
public HelloWorldWrap() {
System.out.println("Constr
}
}
Regards,
Olga.
ASKER
Sorry, one error:
public class HelloWorldWrap extends HelloWorld {
public HelloWorldWrap() {
System.out.println("Constr uctor HelloWorldWrap invoked");
}
}
public class HelloWorldWrap extends HelloWorld {
public HelloWorldWrap() {
System.out.println("Constr
}
}
Hi,
Which ClassLoader do you use? It might be classloader bug.
Igor
Which ClassLoader do you use? It might be classloader bug.
Igor
ASKER
This is my ClassLoader. It defines loadClass new, so that if the class HelloWorld is to be loaded, the class HelloworldWrap will be loaded instead.
class MyCustomClassLoader extends ClassLoader {
private String toWrap = "HelloWorld";
private boolean lock = false;
private byte [] loadClassData(String name) throws IOException {
InputStream in = new FileInputStream(name.repla ce('.',Fil e.separato rChar)+".c lass");
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int b;
while ((b=in.read())!=-1){
buf.write(b);
}
return buf.toByteArray();
}
public synchronized Class loadClass(String name) throws ClassNotFoundException
{
if ((name.equals(toWrap)) && (!lock)) {
name = name+"Wrap";
lock = true;
}
Class c = loadClass(name,false);
return c;
}
protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException
{
byte data [];
Class c = null;
try {
data = loadClassData(name);
} catch (IOException e){
return findSystemClass(name);
}
c = defineClass(name, data, 0, data.length);
if (resolve) resolveClass(c);
return c;
}
}
class MyCustomClassLoader extends ClassLoader {
private String toWrap = "HelloWorld";
private boolean lock = false;
private byte [] loadClassData(String name) throws IOException {
InputStream in = new FileInputStream(name.repla
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int b;
while ((b=in.read())!=-1){
buf.write(b);
}
return buf.toByteArray();
}
public synchronized Class loadClass(String name) throws ClassNotFoundException
{
if ((name.equals(toWrap)) && (!lock)) {
name = name+"Wrap";
lock = true;
}
Class c = loadClass(name,false);
return c;
}
protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException
{
byte data [];
Class c = null;
try {
data = loadClassData(name);
} catch (IOException e){
return findSystemClass(name);
}
c = defineClass(name, data, 0, data.length);
if (resolve) resolveClass(c);
return c;
}
}
> if the class HelloWorld is to be loaded, the
> class HelloworldWrap will be loaded instead.
A-ha! Here is your problem. It loads HelloWorldWrap and finds out that it has superclass called HelloWorld which needs to be loaded. Then it tries to load it and gets HelloWorldWrap again. I don't know how normal class loader should react.
Let's take a step back and you will tell us why do you think you need such substitution. If I would need need to change class at runtime, I would use some of factory patterns (did you read 'Design Patterns' book BTW--it's a must!). I mean, I would create function createHelloWorld() and, say, system property which controls real class to be created:
HelloWorld createHelloWorld(){
String realClass = System.getProperty("real.h ello.class ");
if(realClass == null){
return new HelloWorld();
}
return Class.forName(realClass).n ewInstance ();
}
Regards,
Igor Bazarny,
Brainbench MVP for Java 1
www.brainbench.com
> class HelloworldWrap will be loaded instead.
A-ha! Here is your problem. It loads HelloWorldWrap and finds out that it has superclass called HelloWorld which needs to be loaded. Then it tries to load it and gets HelloWorldWrap again. I don't know how normal class loader should react.
Let's take a step back and you will tell us why do you think you need such substitution. If I would need need to change class at runtime, I would use some of factory patterns (did you read 'Design Patterns' book BTW--it's a must!). I mean, I would create function createHelloWorld() and, say, system property which controls real class to be created:
HelloWorld createHelloWorld(){
String realClass = System.getProperty("real.h
if(realClass == null){
return new HelloWorld();
}
return Class.forName(realClass).n
}
Regards,
Igor Bazarny,
Brainbench MVP for Java 1
www.brainbench.com
ASKER
> Then it tries to load it and gets HelloWorldWrap again.
That's why I have the lock variable - not to do it more than once. And it doesn't come to my class loader twice, to replace HelloWorld again. By using new it comes to defineClass and stops there with this error. It has no possibility more to replace it. With loadClass - newInstance it goes through defineClass without problems, having exactly the same input.
> I mean, I would create function createHelloWorld() and,
> say, system property which controls real class to be
> created
The problem is this is a student project. We have to create a security system which could be used with each application just through configuration. That's, the application itself knows nothing about this replacement, and the class loader knows nothing about application (I've written HelloWorld direct in ClassLoader just for testing). The first idea was to change the JVM. The second - this one with class loader. I have another one - to change bytecode, but before I may try that I must say: no, this one with ClassLoader is impossible.
So, if you have any ideas - they are all welcome.
That's why I have the lock variable - not to do it more than once. And it doesn't come to my class loader twice, to replace HelloWorld again. By using new it comes to defineClass and stops there with this error. It has no possibility more to replace it. With loadClass - newInstance it goes through defineClass without problems, having exactly the same input.
> I mean, I would create function createHelloWorld() and,
> say, system property which controls real class to be
> created
The problem is this is a student project. We have to create a security system which could be used with each application just through configuration. That's, the application itself knows nothing about this replacement, and the class loader knows nothing about application (I've written HelloWorld direct in ClassLoader just for testing). The first idea was to change the JVM. The second - this one with class loader. I have another one - to change bytecode, but before I may try that I must say: no, this one with ClassLoader is impossible.
So, if you have any ideas - they are all welcome.
Oh, I see. Good luck to you. Even with lock variable, your classloader may confuse JVM--it might decide that class extends itself. What other restrictions do you have? If you need your solution to work on several platforms, your trick looks more suspicious. BTW, what kind of security system you need to create? What your wrapper supposed to do? Can't you use java security approach?
ASKER
No, it's just a researc. But thanks anyway. We've already found a solution.
shtern:
This old question needs to be finalized -- accept an answer, split points, or get a refund. For information on your options, please click here-> http:/help/closing.jsp#1
EXPERTS:
Post your closing recommendations! No comment means you don't care.
This old question needs to be finalized -- accept an answer, split points, or get a refund. For information on your options, please click here-> http:/help/closing.jsp#1
EXPERTS:
Post your closing recommendations! No comment means you don't care.
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:
[points to bazarny]
Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
sudhakar_koundinya
EE Cleanup Volunteer
---------------------
If you feel that your question was not properly addressed, or that none of the comments received were appropriate answers, please post your concern in THIS thread.
I will leave a recommendation in the Cleanup topic area that this question is:
[points to bazarny]
Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
sudhakar_koundinya
EE Cleanup Volunteer
---------------------
If you feel that your question was not properly addressed, or that none of the comments received were appropriate answers, please post your concern in THIS thread.
ASKER
Class cl = getClass().getClassLoader(
Object o = cl.newInstance();
This works. But if I use
HelloWorld h = new Helloworld();
it doesn't work.
Regards,
Olga Stern.