9 Replies Latest reply on May 31, 2004 8:22 AM by null null

    inserting duplicated members

    null null Newbie

      Hi,
      is it possible, using Javassist, to insert in an exisiting class duplicated members? I mean, supposing a class has a variable and a method like the following:

      public int variable;
      public void method(){..}

      can I insert a CtField which represents a variable with "variable" name and is an int, and a CtMethod with the "method" name and no one argument?
      I know it does not make sense, but I'd like to know only if it is possible, and in the case why not or why it is.

      Thanks,
      Luca

        • 1. Re: inserting duplicated members
          Shigeru Chiba Expert

          I have just released 3.0 beta!

          This version rejects such a duplicated member.
          In principle, you can add a duplicated member to
          a class file but the JVM will reject that class file
          since it does not pass bytecode verification.

          • 2. Re: inserting duplicated members
            null null Newbie

            Maybe I'm misunderstanding but I've the following code to work on my system:

            CtField fields[]=src.getDeclaredFields();
            CtField addingField=null;

            for(int i=0;i<fields.length;i++) {

            addingField=new CtField(fields.getType(),fields.getName(),dest);
            addingField.setModifiers(fields.getModifiers());
            dest.addField(addingField);
            }

            supposing src and dest are CtClass objects. Now what I cannot understand is why the system is allowing me to copy (and create) objects from the dest class even if the I copy duplicated fields (I mean fields with the same name but different type) from src to dest. Moreover, if I try something similar with methods:

            CtMethod toAdd[]=src.getDeclaredMethods();
            CtMethod copy=null;

            for(int i=0;i<toAdd.length;i++) {
            copy=CtNewMethod.copy(toAdd
            ,dest,null);
            dest.addMethod(copy);
            }

            and the method has the same signature of another one, which already exists in src, I got an ClassFormatException during creation. Why this does not happen with the fields?

            Hope someone can explain me this.

            Luca

            • 3. Re: inserting duplicated members
              Shigeru Chiba Expert

              Are src and dest different CtClass objects?

              If yes, the problem is not adding copied
              methods. I think maybe your way of using a
              class loader is somewhat wrong. Can you show
              me the code that throws ClassFormatError?

              • 4. Re: inserting duplicated members
                null null Newbie

                Well, src and dest are different CtClass, I mean they are produced from different classes. When I try to define the class, in my classloader, as:


                /* create the pools */
                ClassPool aPool=ClassPool.getDefault();
                this.addClasspathToPoll(aPool);
                .....
                byte[] code= aPool.write(className);
                return this.defineClass(className,code,0,code.length);

                I got the exception, if the code produced by the pool is related to a class manipulate with two method with the same signature. Is the above the code you were looking for?

                Thanks,
                Luca

                • 5. Re: inserting duplicated members
                  Shigeru Chiba Expert

                  Here is my thought.

                  The JVM throws an exception if a class has two
                  methods with the same name and signature
                  becuase such a class cannot pass the bytecode
                  verification. This is the spec.

                  I guess the reason that the JVM accepts a class
                  that has two fields with the same name is because
                  the JVM wrongly ignore such duplicated fields,
                  i.e. this is a bug of the JVM.

                  I don't know. Anyway, if you use Javassist 3.0,
                  Javassist does not allow you to create such
                  borken classes!

                  Please try it.

                  • 6. Re: inserting duplicated members
                    null null Newbie

                    Dear Chiba,
                    I'll try it with javassist 3 next week and I will post results. Nevertheless I'm running the posted code oisver jvm 1.4.1 and 1.4.2, thus I don't believe that duplicated fields are due to a bug.
                    What I'd like to understand is how javassist adds a new field. I read an old article from Gosling, "Oak Intermediate bytecode" (ACM SIGPLAN workshop 95) where it talks about the Oak/Java method to access variables. Supposing it is still valid, variables are not accessed thru an offset but trhu a two level offset: first the symbol table is queried and then the access is done at the offset contained in the symbolic table for the specified variable. This means that duplicated variables can exists in a class file, since it suffices to use different symbolic table entries and offsets. This is the theory. As you stated, the bytecode verifier should check for this, but if the bytecode has been rightly produced, thus variable are not considered as duplicated but as different variables with the same name, it has no chance to find it out!
                    Now hod does javassit add a new ctfield? I believe it appends a new entry to what will be the symbolic table, isn't it? Can you explain me?

                    Thanks,
                    Luca

                    • 7. Re: inserting duplicated members
                      Shigeru Chiba Expert

                      Yes, a field is identified by a pair of name and type
                      at the bytecode level.

                      BTW, I found the answer. The JVM Spec book says in Sec 4.5:

                      Each field is described by a field_info structure. No two fields in one class file may have the same name and descriptor.

                      So at the bytecode level, two fields can share the same name if their types are different. I didn't
                      know this fact. :<

                      • 8. Re: inserting duplicated members
                        null null Newbie

                        Well, I suppose it suffices the field_info is different, since even adding fields of the same type works. I've tried it both with a primitice type (an int) and an object (a string), both with the same name and the same access specifier (even if this should not change things) and it works.

                        Luca

                        • 9. Re: inserting duplicated members
                          null null Newbie

                          I've tested javassist 3 (beta), recompiling my sources with the above library, but the behavior of the shown code has not changed. I've substituted the aPool.write() call with a call toBytecode() over the CtClass object, but I'm still able to copy duplicated members as detailed in previous posts.
                          Any idea?

                          Thanks,
                          Luca