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...
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
(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:
[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();
}
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
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.
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.
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.
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.
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
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.
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.
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:
(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.
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!
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.
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.
The bug has been found and fixed for release 1.7. Details are given in bug #775967.
Cheers,
Eric.
Ar you using proguard 1.6.3. There was a problem with this.
/Dirk
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.
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.