Menu

#10 AbstractMethodError in proguard 1.4?

closed-fixed
None
5
2003-01-11
2002-12-06
No

Hi,
Having some problems using Proguard on a rather
large application, basically I'm seeing this error
message after obfuscation:

Exception occurred during event dispatching:
java.lang.AbstractMethodError
at javax.swing.JTree.setModel(JTree.java:693)
at com.wordmap.toolset.ak.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(
InvocationEvent.java:149)
at java.awt.EventQueue.dispatchEvent(
EventQueue.java:332)

This is using windowsNT4.0sp6, j2se 1.3.1_06 and
proguard 1.4.

I was wondering if theres any known problems in
this area, the code in question is too big, clunky &
copyrighted to forward on..

The package in question has a customised tree
component that extends JTree (mostly to add
autoscrolling & a custom page up & down key
action) dosnt attempt to override setModel() at all,
it overrides JTree's no-parameter constructor with a
simple super().. nothing too fancy -- Its
corresponding model is in the same package and
implements TreeModel, but things dont seem to be
getting that far. Code bugs out from an internal
Runnable class used to swap the tree model from
the event thread SwingUtilities.invokeLater() style,
this itself in from an asyncronous jdbc loading
thread ~ This object loader setup may be more
suspect in terms of class depth & complexity for
Proguard.

I'll try to keep plugging away at it until I can break
the problem down some more.. but right now I'll
have to try to swap back to retroguard to get a
shipable app out to the testers -- been having
problems with the obfuscated jar here too..
different problems though.. maybe retroguard
dosnt like 1.3.1_06; I'll drop back a few jvm
versions too see what happens, cant think of any
other changes to the app thay may have effected all
this.

Thanks,

Richard

Related

Bugs: #631
Bugs: #664

Discussion

  • Richard Osbaldeston

    Logged In: YES
    user_id=234263

    Might be a clue.. Just found the culprit behind my
    retroguard problems, dropping back to 1_3_1_02 didnt
    help.. eventually I realised that I'd updated ant to 1.5.1
    over the past few months, going back to ant 1.4.1 and
    the build works as before, no more unknown methods
    or missing fields; again this is retroguard but given
    proguards hertitage and the simularity of the error
    messages.. need to investigate whats been changed
    within ants javac (most likely) or jar tasks.

     
  • Eric Lafortune

    Eric Lafortune - 2002-12-08

    Logged In: YES
    user_id=555208

    The line number in your exception seems to correspond to a
    method call inside the setModel method. In JDK 1.3.1_01 it is
    clearToggledPaths() that is being called; I'm not sure if
    it's still the same in JDK 1.3.1_06. It's a protected method
    that shouldn't be causing any problems. The method is in a
    library class and libraries remain unchanged.

    Some thoughts:

    - You've probably already tried to remove all class files and
    recompile your application? Sometimes old class files still
    hang around, after their source files have been removed.
    Also, some IDEs recompile JDK classes to your output path
    when you've browsed to them. Duplicate copies of Swing
    classes could really mess things up.

    - You're not trying to process the Swing classes as part of
    the -injars options?

    - You're not using the -ignorewarnings option and ignoring
    some vital warnings?

    ProGuard doesn't reuse any obfuscation code or shrinking code
    from RetroGuard, just class parsing code. It seems unlikely
    something is going wrong there.

    You could send me your configuration file and the textual
    output of ProGuard. If you want to create a simple example,
    the component that extends JTree sounds like a good starting
    point.

    Eric.

     
  • Eric Lafortune

    Eric Lafortune - 2002-12-08
    • assigned_to: nobody --> lafortune
     
  • Richard Osbaldeston

    Logged In: YES
    user_id=234263

    Ok, back working on this after the weekend; I'll try to
    push the retroguard oddies to one side then.. although
    the switch from ant 1.4.1 to 1.5.1 seems to be the root
    cause (assume 1.5.1 passes different default javac
    parameters - different source target?) ..even when using
    the self same build.xml file.. very odd

    Bit of history here - this project I'm working on is a
    longstanding one, the build process including
    retroguard was put in place at the end of 2000 and has
    been working successfully across the jvm versions
    since.. we haven't done any releases since the summer,
    but on Friday I needed to add a small customer mod
    (couple of extra reports, very minor change) and re-
    build and much to my horror retroguard fluffed it.. at
    the time I just decided it was finally time to retire
    retroguard and I've been using proguard on my own
    projects as a worthy successor, but after a quick config
    change and rebuild proguard wasn't fairing any better..
    with time pressing and not wanting to introduce
    anything radically new into the build process I had to
    reverse course again and find out why retroguard was
    breaking.. Much of the problems were hidden because
    the only really big change to my setup since the last set
    of builds is my recent upgrade from IntelliJ Idea2.6 to
    Idea 3.0; apparently in that upgrade the internal
    versions of ant shipped with the IDE changed from 1.4
    to 1.5.1. So now I'm trying to break the problems down
    properly; the build.xml and proguard config files are
    attached along with a log of the build & run.. I'm usually
    very careful about wiping any old flaky classes, or
    anything that might creep into the build, the directories
    get nuked from orbit "just to be sure" at the start.. I'm
    equally scruples on my environment & path settings
    including wiping the extra java*.exe from the windows
    dirs to ensure the only java executables are the ones in %
    JAVA_HOME%/bin.

    The build results are run from outside Idea this time, I
    get much the same result; although significantly
    less "duplicate classes" warnings, running ant from
    within Idea I'll get 162 such warnings, outside just the
    eight or so.. I'd guess Idea is additionally passing my
    libdirs in the classpath or something, most of the
    warnings are about wc3 packages like sax & jaxp etc..
    which I'd expect too see duplicated ad-infitum in
    xerces, jdom etc.. despite this change the end result is
    the same java.lang.AbstractMethodError..

    Richard

     
  • Richard Osbaldeston

    build config file & cmd log

     
  • Richard Osbaldeston

    Logged In: YES
    user_id=234263

    Finished trying to create a simple example with a JFrame
    and one other component that extends JTree,
    frustratingly that obfuscates and runs OK. To satisfy my
    own paranoia I've also tried using ant 1.4.1 to build the
    project, and that creates a jar with exactly the same
    problem, so the retroguard stuff is quite a separate
    issue.

    One interesting step forward is I tried a build passing -
    dontshrink to proguard, and that version appears to
    work (at least no AbstractMethodError so far).

    But Im unsure of how to progress the debugging to find
    out what is being inappropriately shrunk..?

     
  • Richard Osbaldeston

    Logged In: YES
    user_id=234263

    ..couple more notes:

    The RetroGuard problems I originally had were very silly;
    the ant 1.4.1 thing was a misnomer the problem turns
    out to have been running retroguard under j2se 1.4,
    which is the standard jvm for IntelliJ Idea.. it doesnt
    complain at all but the result jar is un-useable full of
    missing fields & methods.. Because I ran ant 1.4.1 from
    my command line after Id already dropped back to j2se
    1.3.1_02, and it then worked I didnt twig the real issue,
    so thats one mystery less.

    Still got the same problem with Proguard at the
    moment, although using dontshrink will produce a
    working set of jars; my confusion over the number of
    warnings was the similar to above.. If I run proguard
    under 1.4; Ill get 162 warnings about duplicate classes
    because all the xml parser stuff is duplicated (quite
    correct) again doing from the command line Ill only get
    8 such warnings because Im going though 1.3.1_02. I
    could fix that by changing the build.xml classpath; but
    it doesnt seem to effect this AbstractMethodError.. Also
    tried dumping out all the usage, mapping logs etc.. but I
    cant spot anything obviously wrong with them.

    Richard

     
  • Eric Lafortune

    Eric Lafortune - 2002-12-09

    Logged In: YES
    user_id=555208

    The original RetroGuard doesn't work with JDK 1.4, but
    Thorsten Heit is maintaining an updated version that
    solves this problem. It also adds a few other features,
    although it doesn't shrink. You can find it at
    http://javaguard.sourceforge.net/

    For figuring out what's going wrong with the
    application that is shrunk with ProGuard, you should
    look at line 698 in javax.swing.JTree.setModel, as
    reported in the stack trace. The source code should be
    in the src.jar of your JDK; you can easily browse to it
    using IntelliJ IDEA. If the method called on that line
    is implemented somewhere in your own code, that's a
    helpful indication. If the corresponding abstract
    method in the JDK is in private or package visible
    class, the option -dontskipnonpubliclibraryclasses will
    help (it uses a lot of memory though). Explicitly
    keeping the unjustly removed method should always solve
    the problem. It would be nice to know its cause though.

    Some notes with respect to your configuration file:

    - As of ProGuard 1.4, native method names and their class
    names should be preserved by specifying:

    -keepclasseswithmembernames class * {
    native <methods>;
    }

    - You shouldn't have to preserve any java run-time
    library classes, since they always remain unchanged in
    rt.jar. So you can remove this line:

    -keep public class java.util.TimerTask

    Eric.

     
  • Richard Osbaldeston

     
  • Richard Osbaldeston

    Logged In: YES
    user_id=234263

    That seems to have narrowed down the cause; line 698
    was treeModel.addTreeModelListener
    (treeModelListener).. which was indeed implemented by
    the super class of my treemodel. I've knocked together
    a simple testcase app that illustrates the issue (zip
    attached)..

    The -keep public class java.util.TimerTask in my build
    was only because I've included the class TimerTask
    from the rt.jar in my jar resources.. bit naughty of me,
    but including it allows my application to run under jdk
    1.2.. So in this one case for backwards compatibility it
    was necessary to protect it.

    All that Retroguard stuff was mostly a deadline imposed
    panic, I used JavaGuard before -- infact my RetroGuard
    isnt quite the public version, it contains all kinds of
    patches from the newgroups discussions before
    JavaGaurd & Proguard kicked off.. which is maybe why it
    remained so quite when I bodged the jvm -- I plumb
    forgot that ant picks its jdk from the running jvm
    instance.. and in Idea 3.0 that changes to 1.4 doh!

    Hope the test case is useful,

    Richard

     
  • Eric Lafortune

    Eric Lafortune - 2002-12-17

    Logged In: YES
    user_id=555208

    The problem appears to be caused by what I call a
    retro-fitted interface: interface I contains method m,
    class A implements method m, class B extends A and
    implements I. A while ago, I had solved the problem
    with referencing retro-fitted interface methods, but
    now it pops up again for library interface methods.
    Surprising that noone had noticed this before, although
    the programming style is somewhat unusual.

    I think changing body of the if-clause in
    proguard/shrink/UsageMarker.java, around line 278,
    solves the problem:

    if (recurse)
    {
    String name =
    libraryMethodInfo.getName(libraryClassFile);
    String type =
    libraryMethodInfo.getDescriptor(libraryClassFile);

    // Mark all implementations of the method.
    // Library class methods are supposed to be
    used by
    // default, so we don't want to lose their
    redefinitions.
    //
    // For an abstract method:
    // First go to all concrete classes of
    the interface.
    // From there, travel up and down the
    class hierarchy to mark
    // the method.
    //
    // This way, we're also catching
    retro-fitted interfaces,
    // where a class's implementation of an
    interface method is
    // hiding higher up its class hierarchy.
    //
    // For a concrete method:
    // Simply mark all overriding
    implementations down the
    // class hierarchy.
    libraryClassFile.accept(
    (libraryMethodInfo.getAccessFlags() &
    ClassConstants.INTERNAL_ACC_ABSTRACT)
    != 0 ?

    (ClassFileVisitor)
    new ConcreteClassFileDownTraveler(
    new ClassFileUpDownTraveler(true, true,
    false, true,
    new NamedMethodVisitor(this, name, type))) :

    (ClassFileVisitor)
    new ClassFileUpDownTraveler(false,
    false, false, true,
    new NamedMethodVisitor(this, name, type)));
    }

    Please let me know if you get a chance to try it out.

    Eric.

     
  • Richard Osbaldeston

    Logged In: YES
    user_id=234263

    Thanks for that Eric, only just got round to it after
    Christmas and all, your fix seems to work fine with our
    code now; I've also added the patch for the 'class
    reference in inner class' problem (bug #640658)
    although it isn't an issue within our code.

    Thanks also for worrying about my somewhat unusual
    programming style (grin), I've completed some major
    refactoring for our next release version that does away
    with this retro-fitted interface artefact althougher.

    Richard

     
  • Eric Lafortune

    Eric Lafortune - 2003-01-11
    • status: open --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB