1 2 Previous Next 15 Replies Latest reply: Nov 3, 2004 10:02 AM by Shigeru Chiba RSS

unable to locate the proper class - and some newbie question

Alvin Lim Newbie

Greetings,
I'm a beginner in Java and also Javassist. It's a very great tool.

I have a question. Currently I'm trying to learn Javassist by following the tutorial provided by Mr.Chiba and I encountered few problems.

1- The ClassPool failed to locate the proper class file unless I specify the full path of the class location, eg -> ./build/classes/com/org/solution/....
--------------------------------------------------------------------
Below is my code :
ClassPool pool = ClassPool.getDefault();

pool.insertClassPath("./build/classes/com/org/solution/javaAssist/test");

CtClass clas = pool.get("StringBuilder");
--------------------------------------------------------------------
Is there any other more convenient way? For example, to make the classLoader automatically refer to the path where I put my compiled classes.

2- When I call writeFile(), it will write the modified file into the root directory. Again, is there any other way besides explicitly put the destination where I want to put the newly modified file by calling writeFile(java.lang.String directoryName).

3- Pruning and Frozen. What does these 2 mean? I know frozen means you can no longer modify the class whereas pruning is you can no longer read or load it. Is my assumption correct?

Hope you guys can help. I've tried to read through the forum, but I really need help quite urgently for my project.
Thanks in advance.


Cheers,
Alvin Lim
* someone who has only 3 months working experience ;) *

  • 1. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    hi again,
    seems like no1 answer my questions :( maybe its too simple.

    anyway, i have another doubt over here. my current situation is to generate value object in runtime from a set of configuration files. I tried to add a new field inside........but I found out that there's no CtClass.stringType or any String relevant type inside. So what if I wanted to add something like "private String name" inside the newly generated VO?

    and how bout the modifier. How can I set the modified of the field?

    Hope someone can help me. Thanks in advance.

  • 2. Re: unable to locate the proper class - and some newbie ques
    Shigeru Chiba Expert

    Wow, many questions! :)


    1- The ClassPool failed to locate the proper class file unless I specify the full path of the class location, eg -> ./build/classes/com/org/solution/....

    Javassist uses CLASS_PATH. The real problem in your code is not
    the class path.
    CtClass clas = pool.get("StringBuilder");

    This is unfortunately wrong. All the class names must be fully
    qualified. So you had needed to say "com.org.solution/javaAssist/test/StringBuilder".

    (I have a plan to introduce a mechanism similar to import, though.)


    is there any other way besides explicitly put the destination where I want to put the newly modified file by calling writeFile(java.lang.String directoryName).


    ... Do you really need a way to change the default root directory?
    I appreciate if you are satisfied with writeFile(String)... :)


    3- Pruning and Frozen. What does these 2 mean? I know frozen means you can no longer modify the class whereas pruning is you can no longer read or load it. Is my assumption correct?


    yes, frozen means you cannot modify the class.
    Pruning means method bodies in CtClass has been deleted to save
    memory space. This is becaues some users said they processed a
    large number of class files and thus caused memory shortage.
    You can still read member signatures of pruned CtClass.

    However, people including Bill Burke do not seem to like pruning.
    This memory space optimization might be turned off in the next
    release. :< (pruning is off in the current HEAD in CVS.)

    Chiba


  • 3. Re: unable to locate the proper class - and some newbie ques
    Shigeru Chiba Expert

    Oops, another two questions.


    but I found out that there's no CtClass.stringType or any String relevant type inside. So what if I wanted to add something like "private String name" inside the newly generated VO?


    Use ClassPool#get.
    ClassPool pool = ... ;
    CtClass stringType = pool.get("java.lang.String");
    


    Or use CtField#make.

    CtClass cc = ... ;
    CtField f = CtField.make("private java.lang.String name;", cc);
    cc.addField(f);
    


    Chiba

  • 4. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    Hi,
    Thanks a lot for the reply Mr.Chiba. Really appreciate it. Anyway, perhaps i'm a problematic person, coz i have more questions for u. *lol*

    Ok, I have actually solved the previous questions....and here it is, some new problems.

    My current program works like this (value obj generation) :

    1. Input value is the name of the Vo to generate.

    2. Check whether it is inside a map.

    3. If yes, get the CtClass from the map, use
    clas = ctClass.toClass();
    return (ValueObject) clas.newInstance();

    4. If no, then generate the class by adding fields, methods, etc. Then return the class by doing the same thing as in (3).

    5. I tested to first, call the VO, and since it doesnt exist, it is generated, then i again, call the VO, and it found that it is already in the map, so it load from the map then the problem occurs.

    Below is the msg:

    javassist.CannotCompileException: by java.lang.LinkageError: duplicate class definition: com/PersonVO
    at javassist.CtClass.toClass(CtClass.java:950)
    at javassist.CtClass.toClass(CtClass.java:910)
    at com.generateProxy(ValueObjectTransformer.java:58)
    at com.main(VOGeneratorTest.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at com.intellij.rt.execution.application.AppMain.main(Unknown Source)

    Sorry if the msg is a bit messy.
    Also, when i tried to use -->

    Loader c1 = new Loader(pool);
    Class abc = c1.loadClass(some class path n name);
    return (ValueObject) abc.newInstance();

    It throws ClassCastException

    Sorry for asking too much :D Thx in advance!

    Cheers,
    ALvin Lim

  • 5. Re: unable to locate the proper class - and some newbie ques
    Shigeru Chiba Expert

     

    javassist.CannotCompileException: by java.lang.LinkageError: duplicate class definition: com/PersonVO


    This means the class loader has been already loaded PersonVO and
    thus it cannot load your modified version of PersonVO. I guess your
    code includes PersonVO as a type name.

    Loader c1 = new Loader(pool);
    Class abc = c1.loadClass(some class path n name);
    return (ValueObject) abc.newInstance();


    It throws ClassCastException


    This is a problem called version barrier. You cannot cast a class type
    into another one loaded by another class loader.

    For more details, please read section 3.2 of the Javassist tutorial.

    Chiba

  • 6. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    Hi Mr. Chiba,
    Thanks for your reply. I think I get what you mean. I somehow modified my VO generator so that it only loads the object once and store in somewhere (not efficient, but that's the only way I can think of to bypass the class loading stuff).

    Really thanks a lot. I'll post more questions here if I don't understand something.

    Thanks alot.

    Cheers,
    Alvin Lim

  • 7. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    I have another question here.
    Let say we have a modified class in JVM A, so if we are to pass the modified class to JVM B through RMI, will it cause any problem?
    Or maybe you have any better suggestion to do this?

    Thanks in advance

  • 8. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    Hi again,
    I have another problem (again...never ending problems). This time, I really really have no idea what is happening.

    As I've said earlier, I tried to use javassist to generate run-time Value Object (there's no physical file). Then after that, I will pass the instance of the newly generate VO through EAI (then to DB). Some weird errors occurred. Even if I somehow provide the physical class.........the error is the same.

    ----------------------------------------------------------
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
    java.lang.ClassNotFoundException: com.temp.EmployeeVO: This error could indicate that a component was deployed on a cluster member but not other members of that cluster. Make sure that any component deployed on a server that is part of a cluster is also deployed on all other members of that cluster
    at weblogic.rjvm.BasicOutboundRequest.sendReceive(BasicOutboundRequest.java:108)
    at weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:284)
    at weblogic.rmi.cluster.ReplicaAwareRemoteRef.invoke(ReplicaAwareRemoteRef.java:244)
    at com.ejb.CommonGenericEJB_e1n9qi_EOImpl_813_WLStub.callEAIManager(Unknown Source)
    at com.ORBSPerformanceTest.testManualInsert(ORBSPerformanceTest.java:119)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at junit.framework.TestCase.runTest(TestCase.java:154)
    at junit.framework.TestCase.runBare(TestCase.java:127)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:118)
    at junit.framework.TestSuite.runTest(TestSuite.java:208)
    at junit.framework.TestSuite.run(TestSuite.java:203)
    at junit.textui.TestRunner.doRun(TestRunner.java:116)
    at com.intellij.rt.execution.junit2.IdeaJUnitAgent.doRun(Unknown Source)
    at junit.textui.TestRunner.start(TestRunner.java:172)
    at com.intellij.rt.execution.junit.TextTestRunner2.startRunnerWithArgs(Unknown Source)
    at com.intellij.rt.execution.junit2.JUnitStarter.prepareStreamsAndStart(Unknown Source)
    at com.intellij.rt.execution.junit2.JUnitStarter.main(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at com.intellij.rt.execution.application.AppMain.main(Unknown Source)
    ----------------------------------------------------------

    I really ran out of ideas trying to solve this thing. Please help, i need them desperately.

    Thanks.

  • 9. Re: unable to locate the proper class - and some newbie ques
    Shigeru Chiba Expert

    I don't have any idea. Have you considered this?

    java.lang.ClassNotFoundException: com.temp.EmployeeVO: This error could indicate that a component was deployed on a cluster member but not other members of that cluster. Make sure that any component deployed on a server that is part of a cluster is also deployed on all other members of that cluster



  • 10. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    Hi again,
    I donno whether the problem is with the way I deploy my project. My entire project is an EJB (web application). Thus, when I run my project, it is in EJB. THus when I JAR my project into an EJB, the compiler can only JAR whatever classes I have and not those that have not been generated.

    If I am to use on-the-fly byte code generation, it will cause error since there is no physical class reference to be JAR-ed inside the EJB.

    I somehow changed it to pregenerated classes, so that when i deploy the EJB, those classes have already been generated physically and are deployed together with the rest of the classes. Then it's running fine, no error. :T

    haha, is there any other better way of doing this?

    Thanks again and sorry for taking too much of ur time here.

  • 11. Re: unable to locate the proper class - and some newbie ques
    Shigeru Chiba Expert

    Generating physical class files in advance
    is the simplest way. Otherwise, you might
    be able to modify a class loader that loads
    your EJB so that the class loader also can find
    "virtual" class files generated on the fly.

  • 12. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    Hi Chiba,
    Thanks for your reply. Currently we're using weblogic server to deploy our EJB. If we are to do the 2nd approach, means we're to modify the class loader of the EJB inside weblogic or maybe somehow create a new one to replace it (which I have no idea how to).

    Anyway, I guess I don't have any option since time is limited but I would really like to know how can I do the 2nd approach. ;)

    Thanks a lot Mr Chiba. You really helped me out a lot.

  • 13. Re: unable to locate the proper class - and some newbie ques
    Shigeru Chiba Expert

    I think JBoss has API to substitute a user-defined
    class loader for the original one. WebLogic should
    have such a API... :-p

    Chiba

  • 14. Re: unable to locate the proper class - and some newbie ques
    Alvin Lim Newbie

    Hi again,
    I donno whether weblogic has such thing, but I will try to find out.

    Another question, hehe, hope I am not causing you too much troubles with so many questions.

    How do I accommodate for data types like char[] or byte[].... :D

    Thanks again in advance

1 2 Previous Next