Menu

JDK 1.4.2

Help
Noah Body
2003-06-29
2003-07-29
  • Noah Body

    Noah Body - 2003-06-29

    Hi,

    I recently updated my JDK to 1.4.2 FCS from 1.4.2 Beta, now when I run my Ant ProGuard task I get this (previously it was working fine)...

    [proguard] Removing unused library classes...
    [proguard]     Original number of library classes: 8796
    [proguard]     Final number of library classes:    83
    [proguard] Shrinking...
    [proguard] Removing unused program classes and class elements...
    [proguard]     Original number of program classes: 298
    [proguard]     Final number of program classes:    216
    [proguard] Obfuscating...
    [proguard] Renaming program classes and class elements...

    BUILD FAILED
    file:/home/projects/test/build.xml:69: java.lang.ClassCastException: java.lang.Object }

    So my question is, does anyone have ProGuard working with JDK 1.4.2 FCS?? Or, is there anything I can do to get a more descriptive error message?

    Thanks.

     
    • Noah Body

      Noah Body - 2003-06-29

      Sorry,

      I reverted to JDK 1.4.1 and still got the same error so it's likely not a JDK problem.

      I'd still appreciate any pointers on what that error could be.

      Here's the ant -debug output showing the stack-trace:

      file:/home/projects/test/build.xml:69: java.lang.ClassCastException: java.lang.Object
      at proguard.ant.ProGuardTask.execute(ProGuardTask.java:605)
      at org.apache.tools.ant.Task.perform(Task.java:319)
      at org.apache.tools.ant.Target.execute(Target.java:309)
      at org.apache.tools.ant.Target.performTasks(Target.java:336)
      at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
      at org.apache.tools.ant.Project.executeTargets(Project.java:1250)
      at org.apache.tools.ant.Main.runBuild(Main.java:610)
      at org.apache.tools.ant.Main.start(Main.java:196)
      at org.apache.tools.ant.Main.main(Main.java:235)
      Caused by: java.lang.ClassCastException: java.lang.Object
      at proguard.obfuscate.MemberInfoObfuscator.newMemberName(MemberInfoObfuscator.java:272)
      at proguard.obfuscate.ClassFileRenamer.visitRefCpInfo(ClassFileRenamer.java:243)
      at proguard.obfuscate.ClassFileRenamer.visitMethodrefCpInfo(ClassFileRenamer.java:233)
      at proguard.classfile.MethodrefCpInfo.accept(MethodrefCpInfo.java:48)
      at proguard.classfile.ProgramClassFile.constantPoolEntriesAccept(ProgramClassFile.java:364)
      at proguard.obfuscate.ClassFileRenamer.visitProgramClassFile(ClassFileRenamer.java:80)
      at proguard.classfile.ProgramClassFile.accept(ProgramClassFile.java:355)
      at proguard.classfile.ClassPool.classFilesAccept(ClassPool.java:116)
      at proguard.ProGuard.obfuscate(ProGuard.java:430)
      at proguard.ProGuard.execute(ProGuard.java:586)
      at proguard.ant.ProGuardTask.execute(ProGuardTask.java:601)
      ... 8 more
      --- Nested Exception ---
      java.lang.ClassCastException: java.lang.Object
      at proguard.obfuscate.MemberInfoObfuscator.newMemberName(MemberInfoObfuscator.java:272)
      at proguard.obfuscate.ClassFileRenamer.visitRefCpInfo(ClassFileRenamer.java:243)
      at proguard.obfuscate.ClassFileRenamer.visitMethodrefCpInfo(ClassFileRenamer.java:233)
      at proguard.classfile.MethodrefCpInfo.accept(MethodrefCpInfo.java:48)
      at proguard.classfile.ProgramClassFile.constantPoolEntriesAccept(ProgramClassFile.java:364)
      at proguard.obfuscate.ClassFileRenamer.visitProgramClassFile(ClassFileRenamer.java:80)
      at proguard.classfile.ProgramClassFile.accept(ProgramClassFile.java:355)
      at proguard.classfile.ClassPool.classFilesAccept(ClassPool.java:116)
      at proguard.ProGuard.obfuscate(ProGuard.java:430)
      at proguard.ProGuard.execute(ProGuard.java:586)
      at proguard.ant.ProGuardTask.execute(ProGuardTask.java:601)
      at org.apache.tools.ant.Task.perform(Task.java:319)
      at org.apache.tools.ant.Target.execute(Target.java:309)
      at org.apache.tools.ant.Target.performTasks(Target.java:336)
      at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
      at org.apache.tools.ant.Project.executeTargets(Project.java:1250)
      at org.apache.tools.ant.Main.runBuild(Main.java:610)
      at org.apache.tools.ant.Main.start(Main.java:196)
      at org.apache.tools.ant.Main.main(Main.java:235)

      Thanks.

       
      • Eric Lafortune

        Eric Lafortune - 2003-06-30

        As Dirk pointed out, this is a bug that should have been fixed in release 1.6.2. Some data structures from the shrinking step were left behind, causing confusion in the obfuscation step. I've added a call that should clean up data structures between the two steps.

        So far, I've had a single report of it still happening, but I haven't been able to reproduce it. Are you sure you're using the right jar? Unfortunately, the runtime message will just display "ProGuard, version 1.6", so you'll have to double-check you're using the jar in proguard1.6.2/lib.

        If it's still a problem, I'd really appreciate a test case (preferably simple code + configuration).

        Cheers,

        Eric.

         
        • Noah Body

          Noah Body - 2003-06-30

          I've done some more digging...

          Consider this construct (note that this is not a real class, but does illustrate how I structured the failing classes in question):

          class Test extends JPanel
          {
            Test()
            {
              initActions();
            }

            private void initActions()
            {
              ActionMap am = getActionMap();
              am.put( "cancel", new AbstractAction()
              {
                public void actionPerformed( ActionEvent e )
                {
                  System.out.println( "cancel" );
                }
              } );
            }
          }

          Note the use of the anonymous class - if I remove that am.put() call, the obfuscation works completely without error.

          Hope that was helpful to you.

          -M.

           
          • Eric Lafortune

            Eric Lafortune - 2003-07-01

            Thanks for the example; this is really useful. However, the example is working fine for me so far. The steps I followed, using Sun JDK 1.3.1_01 on Redhat Linux 9.0:

            - Copied code into src/Test.java, adding imports.
            - Compiled to classes/Test*.class.
            - Processed with proguard1.6.2/lib/proguard.jar, using these options

                -libraryjars <java.home>/lib/rt.jar
                -injars classes
                -outjar classes2
                -keep class Test { <init>(); }

            The console output:

                ProGuard, version 1.6
                Reading program directory [classes]
                Reading library jar [/usr/local/java/jdk1.3.1_01/jre/lib/rt.jar]
                Writing output directory [classes2]...
                Adding resources from directory [classes]

            Repeating the above procedure with JDK 1.4.1_01 worked fine as well.

            Can you tell me what you did differently? Could you try it outside of Ant?

            Eric.

             
            • Noah Body

              Noah Body - 2003-07-02

              Hi,

              In isolation it all works fine for me too.

              Unfortunately it looks like some combination of classes that's causing the problem.

              I have been doing more digging but can't get a specific, isolated, test case where it fails.

              All I can tell you is that the other place it failed (after I had removed the other offending classes) was in a structure like this (this is just pseudo code from memory):

              public class MyClass
              {
                private KeyStroke keyStroke;
                private Action action;

                public( String key, String value )
                {
                  keyStroke = KeyStroke.getKeyStroke( key );
                  action = new MyAction( value );
                }

                private class MyAction( String value ) extends AbstractAction 
                {
                  // etc.
                }
              }

              In this example, if I don't make the call to instantiate the inner class the obfuscation works fine.

              So that's two slightly different cases where I'm using inner classes that causes the failure.

              Unfortunately again, if I just use that class in isolation, and not in the context of the other 400 class files I have in my project, it doesn't fail.

              And it fails just the same running from the command-line as it does running in the Ant task.

              The only other thing that I can think that I might have changed from when it did work to when it didn't was that I introduced a class hierarchy that extended some base classes that in turn used static initialisation.

              For example:

              abstract public class Base1
              {
                protected String property = Application.getProperty( "name" );
              }

              ...and then...

              abstract public class Base2 extends Base 1
              {
                protected String config = Application.config( "config.xml" );
              }

              ...and then...

              public class SomeImpl extends Base2
              {
                public SomeImpl()
                {
                  System.out.println( config );
                }
              }

              Sorry I can't be much more help than that.

              In case it's useful:
              JDK1.4.2 FCS
              JDK1.4.1_03
              Mandrake 9.1

               
            • Noah Body

              Noah Body - 2003-07-10

              I have still been digging further into this...

              One more piece of info that is hopefully helpful to you is that if I specify shrinking="no" in my Ant task I don't get any exception being thrown.

              -M.

               
              • Eric Lafortune

                Eric Lafortune - 2003-07-10

                Yes, the exception is caused by an object in the class data structure that is left over from the shrinking step, even though it should have been cleared before starting the obfscation step. In fact, the only other similar report mentions that you can make the problem go away by testing with "!= null" and "instanceof String" (and possibly returning null) before doing the class cast at

                proguard.obfuscate.MemberInfoObfuscator.newMemberName(MemberInfoObfuscator.java:272)

                You could also run ProGuard twice: first for shrinking, then for obfuscating.

                Still, I'd prefer to figure out why this object is still there. Could you add some debug code before this line:

                proguard.obfuscate.ClassFileRenamer.visitRefCpInfo(ClassFileRenamer.java:243)

                Useful information would be
                classFile.getName(),
                refCpInfo.referencedClassFile.getName(),
                refCpInfo.referencedMemberInfo.getName(referencedMemberInfo.referencedClassFile),
                refCpInfo.referencedMemberInfo.getDescriptor(referencedMemberInfo.referencedClassFile).

                The values right before the exception would be interesting, along with the relevant class hierarchy of the listed class and method. Do you expect the printed method to be used in your code?

                Thanks for your help.

                Eric.

                 
                • Noah Body

                  Noah Body - 2003-07-11

                  I added some trace code similar to that which you suggested.

                  One of the getName() invocations ultimately causes a call to programClassFile.getCpString() like this:

                   
                  • Noah Body

                    Noah Body - 2003-07-11

                    (Sorry for the previous post, hit submit by accident). Here's the full post:

                    Hi,

                    I added some trace code similar to that which you suggested.

                    One of the getName() invocations ultimately causes a call to programClassFile.getCpString() like this:

                    public String getCpString(int cpIndex)
                    {
                       return ((Utf8CpInfo)constantPool[cpIndex]).getString();
                    }

                    The object class that is actually returned in the failing case is not a Utf8CpInfo, it's a proguard.classfile.ClassCpInfo and causes a ClassCastException.

                    The class that throws up the error is used in about half a dozen unique places within my application.

                    The following trace shows the result of these trace statements inserted into ClassFileRenamer as suggested:

                    System.out.println( "ClassFileName: " + classFile.getName() );
                    System.out.println( "RefdClassFileName: " + refCpInfo.referencedClassFile.getName() );
                    ClassFile[] cfs = referencedMemberInfo.referencedClassFiles;
                    for( int i = 0; cfs != null && i < cfs.length; i ++ )
                    {
                       ClassFile cf = cfs[i];
                       System.out.println( "ref: " + refCpInfo.referencedMemberInfo.getName( cf ));
                       System.out.println( "ref: " + refCpInfo.referencedMemberInfo.getDescriptor( cf ));
                    }

                    [proguard] -----------------------------------------------
                    [proguard] ClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] RefdClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] -----------------------------------------------
                    [proguard] ClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] RefdClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] -----------------------------------------------
                    [proguard] ClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] RefdClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] -----------------------------------------------
                    [proguard] ClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] RefdClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] -----------------------------------------------
                    [proguard] ClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] RefdClassFileName: com/somecompany/ComponentEvent
                    [proguard] -----------------------------------------------
                    [proguard] ClassFileName: com/somecompany/AbstractComponentModel
                    [proguard] RefdClassFileName: com/somecompany/ComponentModelListener
                    [proguard] getName: classFile = com/somecompany/ComponentEvent
                    BUILD FAILED
                    file:/home/projects/build.xml:66: java.lang.ClassCastException: proguard.classfile.ClassCpInfo
                            at proguard.ant.ProGuardTask.execute(ProGuardTask.java:605)
                            at org.apache.tools.ant.Task.perform(Task.java:319)
                            at org.apache.tools.ant.Target.execute(Target.java:309)
                            at org.apache.tools.ant.Target.performTasks(Target.java:336)
                            at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
                            at org.apache.tools.ant.Project.executeTargets(Project.java:1250)
                            at org.apache.tools.ant.Main.runBuild(Main.java:610)
                            at org.apache.tools.ant.Main.start(Main.java:196)
                            at org.apache.tools.ant.Main.main(Main.java:235)
                    Caused by: java.lang.ClassCastException: proguard.classfile.ClassCpInfo
                            at proguard.classfile.ProgramClassFile.getCpString(ProgramClassFile.java:294)
                            at proguard.classfile.ProgramMemberInfo.getName(ProgramMemberInfo.java:190)
                            at proguard.obfuscate.ClassFileRenamer.visitRefCpInfo(ClassFileRenamer.java:250)
                            at proguard.obfuscate.ClassFileRenamer.visitInterfaceMethodrefCpInfo(ClassFileRenamer.java:228)
                            at proguard.classfile.InterfaceMethodrefCpInfo.accept(InterfaceMethodrefCpInfo.java:48)
                            at proguard.classfile.ProgramClassFile.constantPoolEntriesAccept(ProgramClassFile.java:364)
                            at proguard.obfuscate.ClassFileRenamer.visitProgramClassFile(ClassFileRenamer.java:80)
                            at proguard.classfile.ProgramClassFile.accept(ProgramClassFile.java:355)
                            at proguard.classfile.ClassPool.classFilesAccept(ClassPool.java:116)
                            at proguard.ProGuard.obfuscate(ProGuard.java:430)
                            at proguard.ProGuard.execute(ProGuard.java:586)
                            at proguard.ant.ProGuardTask.execute(ProGuardTask.java:601

                    (This flies in the face of what I reported earlier, none of those classes mentioned in the trace have inner classes.)

                    Some detail on the class hierarchy of the classes named in the trace:

                    package com.somecompany.AbstractComponentModel

                    abstract public class AbstractComponentModel extends ArrayList implements ComponentModel
                    {
                      private EventListenerList listenerList = new EventListenerList();

                      public void clear()
                      {
                        super.clear();
                        fireItemChanged();
                      }

                      public void addModelListener( ComponentModelListener listener )
                      {
                        listenerList.add( ComponentModelListener.class, listener );
                      }

                      public void removeModelListener( ComponentModelListener listener )
                      {
                        listenerList.remove( ComponentModelListener.class, listener );
                      }

                      protected void fireItemChanged()
                      {
                        ComponentEvent evt = new ComponentEvent();

                        EventListener[] listeners = listenerList.getListeners( ComponentModelListener.class );

                        for( int i = listeners.length - 1; i >= 0; i -- )
                          ( ( ComponentModelListener )listeners[ i ] ).componentChanged( evt );
                      }
                    }

                    package com.somecompany.ComponentModel

                    public interface ItemListModel
                    {
                      public void addModelListener( ComponentModelListener listener );
                      public void removeModelListener( ComponentModelListener listener );
                    }

                    package com.somecompany.ComponentEvent

                    public class ComponentEvent
                    {
                      private int index;

                      public int getIndex()
                      {
                        return index;
                      }

                      public void setIndex( int index )
                      {
                        this.index = index;
                      }
                    }

                    package com.somecompany.ComponentModelListener

                    public interface ComponentModeListener
                    {
                      public void componentChanged( ComponentEvent evt );
                    }

                    I then have half a dozen classes that provide concrete implementations of AbstractComponentModel.

                    I hope that's helpful.

                    -Mark.

                     
                    • Noah Body

                      Noah Body - 2003-07-11

                      Sorry, a small copy and paste error meant I gave you the wrong interface.

                      Replace "ItemListModel" with "ComponentModel".

                      Makes no actual difference though, the structure is the same.

                      I also screwed the package statements up as I was rushing it a bit! In the real source code those errors aren't there of course!

                       
                      • Eric Lafortune

                        Eric Lafortune - 2003-07-18

                        Thanks for inserting the debug code, but it's not quite what I meant (the class file in the argument has to be the one that corresponds to the class member, or you'll get new exceptions indeed). I should have given complete source code. So here it is, for ClassFileRenamer, line 243 (before "String newMemberName = ..."):

                        // These methods return the class and class member names.
                        System.out.println("ClassFile: "+classFile.getName());
                        System.out.println("Member class: "+refCpInfo.getClassName(classFile));
                        System.out.println("        name: "+refCpInfo.getName(classFile));
                        System.out.println("        type: "+refCpInfo.getType(classFile));
                        // These fields point to the actual class and class member objects.
                        // The names may differ if they've already been renamed.
                        ProgramClassFile  refClassFile  = refCpInfo.referencedClassFile;
                        ProgramMemberInfo refMemberInfo = refCpInfo.referencedMemberInfo;
                        System.out.println("Referenced member class: "+refClassFile.getName());
                        System.out.println("                   name: "+refMemberInfo.getName(refClassFile));
                        System.out.println("                   type: "+refMemberInfo.getDescriptor(refClassFile));

                        This should work, up to the point where the next statement causes
                        the ClassCastException. The classes involved and their hierarchies
                        should shed some light on the problem.

                        Thanks for your patience. I'm hoping to resolve this problem soon. You can always send me details be e-mail.

                        Eric.

                         
                        • Noah Body

                          Noah Body - 2003-07-27

                          Hi,

                          Apologies for the misunderstanding.

                          I inserted the debug code that you described. It didn't really give me any more useful information as it pointed to classes that were definitely used, but once I tried to isolate the class hierarchy in a stand-alone test-case I could not get ProGuard to fail again.

                          There was nothing unusual in the referenced classes over and above having anonymous inner classes for concrete implementations of Swing's AbstractAction class.

                          Sorry I can't be any more help than that, I just can't get an isolated test case.

                           
                          • Eric Lafortune

                            Eric Lafortune - 2003-07-29

                            The bug has been found and fixed for release 1.7. Details are given in bug #775967.

                            Cheers,

                            Eric.

                             
    • Dirk Schnelle-Walka

      Ar you using proguard 1.6.3. There was a problem with this.

      /Dirk

       
    • Noah Body

      Noah Body - 2003-06-30

      Hi,

      I'm using 1.6.2, the latest version downloadable from SourceForge.

      I can't see any way to get 1.6.3 from SourceForge (yet?).

      Thanks.

       
    • Noah Body

      Noah Body - 2003-06-30

      It's definitely ProGuard 1.6.2 I have.

      I have it installed in /home/tools/proguard1.6.2 and soft-linked via /home/tools/proguard

      I even did a further test where I deleted the soft-link and used the absolute path to the 1.6.2 jar file.

      I can't give you a complete test case but here's an abridged build.xml that might be a little help:

        <property name="proguard.lib.home" value="/home/tools/proguard"/>   <!-- 1.6.2 -->
        <property name="target.jdk.home" value="/home/tools/j2sdk"/>        <!-- 1.4.2 -->
        <property name="log4j.lib.home" value="/home/tools/jakarta-log4j"/> <!-- 1.2.8 -->

        <taskdef name="proguard" classname="proguard.ant.ProGuardTask">
          <classpath>
            <fileset dir="${proguard.lib.home}">
              <include name="**/*.jar"/>
            </fileset>
          </classpath>
        </taskdef>

        <target name="obfuscate" depends="jar">

          <proguard outjar="${dist.home}/dest.jar" verbose="true" defaultPackage="">

            <injar name="${dist.home}/source.jar"/>

            <libraryjar name="${target.jdk.home}/jre/lib/rt.jar"/>

            <libraryjar name="${log4j.lib.home}/log4j.jar"/>

            <keep name="test.components.ComponentTest">
              <method access="public static" name="main(java.lang.String[])" />
            </keep>

            <keep name="com.xxx.xxx.xxx.Main">
              <method access="public static" name="main(java.lang.String[])" />
            </keep>

            <keep name="com.xxx.xxx.xxx.plaf.*"/>

            <keep name="junk.RuleUI"/>

            <keepclasseswithmembernames>
              <method access="native"/>
            </keepclasseswithmembernames>

          </proguard>

        </target>

      (I don't get any warnings about duplicated classes or anything like that.)

      The source.jar contains about 350 class files for my project.

      Like I said in an earlier post, this had all been working. I then changed TWO things, I don't remember the order I did this:

      - Introduce JDK1.4.2 FCS rather than 1.4.2 beta.

      - Introduce Log4J to my project.

      And of course it's possible I changed something else - but I did not touch the build.xml or anything to do with ProGuard.

      I can't give you my source code for a test case, but I'll happily try any suggestions out.

      Thanks.

       
MongoDB Logo MongoDB