Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-62723

Build fails with "java.lang.IllegalArgumentException: Method perform not found in hudson.plugins.analysis.core.HealthAwareRecorder"

    XMLWordPrintable

Details

    • Jenkins 2.248

    Description

      Hello,

      after updating jenkins from 2.239 to 2.241 our jobs started to fail:

      BUILD SUCCESSFUL
      Total time: 10minutes 49seconds
      New run name is '20.3.0.1-#40123'
      ERROR: Build step failed with exception
      java.lang.IllegalArgumentException: Method perform not found in hudson.plugins.analysis.core.HealthAwareRecorder (or it is private, finalor static)
      	at hudson.Util.getMethod(Util.java:1462)
      	at hudson.Util.getMethod(Util.java:1455)
      	at hudson.Util.getMethod(Util.java:1455)
      	at hudson.Util.isOverridden(Util.java:1439)
      	at jenkins.tasks.SimpleBuildStep.perform(SimpleBuildStep.java:110)
      	at hudson.tasks.BuildStepCompatibilityLayer.perform(BuildStepCompatibilityLayer.java:78)
      	at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:20)
      	at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:741)
      	at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:690)
      	at hudson.model.Build$BuildExecution.post2(Build.java:186)
      	at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:635)
      	at hudson.model.Run.execute(Run.java:1905)
      	at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
      	at hudson.model.ResourceController.execute(ResourceController.java:97)
      	at hudson.model.Executor.run(Executor.java:428)
      Build step '[Deprecated] Scan workspace for open tasks'marked build as failure
      Archiving artifacts
      Recording fingerprints
      [Java] Skipping execution of recorder since overall result is 'FAILURE'
      

       
      In the german version of the GUI this particular post build step is not marked as deprecated, only in  the build log it is possible to see that this build step seems to be deprecated and therefor maybe problematic.

      Is there any alternative step available, that i am not aware of? I guess the exception happend above should not occur as well,right?
       
      Greetings from Berlin,
      Heiko

      Attachments

        Issue Links

          Activity

            drulli Ulli Hafner added a comment -

            These plugins are end-of-life since Spring 2019. Please upgrade to https://github.com/jenkinsci/warnings-ng-plugin.

            drulli Ulli Hafner added a comment - These plugins are end-of-life since Spring 2019. Please upgrade to https://github.com/jenkinsci/warnings-ng-plugin .
            jglick Jesse Glick added a comment -

            Core regression also apparently affecting phabricator-plugin and perhaps many others.

            jglick Jesse Glick added a comment - Core regression also apparently affecting phabricator-plugin and perhaps many others.
            jglick Jesse Glick added a comment -

            I suspect the root cause is JENKINS-30002. Should be possible to verify in IsOverriddenTest.

            jglick Jesse Glick added a comment - I suspect the root cause is JENKINS-30002 . Should be possible to verify in IsOverriddenTest .

            Yay for poor API docs.

            {Util.isOverridden()}

            is documented as "Checks if the method defined on the base type with the given arguments is overridden in the given derived type."

            There is/was no reason to expect it would throw for any reason (other than real failures).
            Nor does it specify that it disregards final methods, which seems weird to me: In inheritance chain A > B > C, if I ask whether C overrides method M from A, I expect the answer to be yes when B and/or C override M, regardless of finality.

            In addition, the logic assumes subclassing only - it does not handle cases where the base is an interface (it walks superclasses only, so never sees the interface method).

            I'll look at adding an alternative to isOverridden() (maybe isDefaulted()?) that handles this use case. And I'll improve the docs for isOverridden() while I'm at it.

            zastai Tim Van Holder added a comment - Yay for poor API docs. {Util.isOverridden()} is documented as "Checks if the method defined on the base type with the given arguments is overridden in the given derived type." There is/was no reason to expect it would throw for any reason (other than real failures). Nor does it specify that it disregards final methods, which seems weird to me: In inheritance chain A > B > C, if I ask whether C overrides method M from A, I expect the answer to be yes when B and/or C override M, regardless of finality. In addition, the logic assumes subclassing only - it does not handle cases where the base is an interface (it walks superclasses only, so never sees the interface method). I'll look at adding an alternative to isOverridden() (maybe isDefaulted()?) that handles this use case. And I'll improve the docs for isOverridden() while I'm at it.
            jglick Jesse Glick added a comment -

            I have a unit test at least, hold on a sec…

            jglick Jesse Glick added a comment - I have a unit test at least, hold on a sec…
            jglick Jesse Glick added a comment -

            Filed a unit test reproducing a similar stack trace. Passing back to you for a fix and Javadoc improvements.

            jglick Jesse Glick added a comment - Filed a unit test reproducing a similar stack trace. Passing back to you for a fix and Javadoc improvements.
            jglick Jesse Glick added a comment -

            I do not think we need a new API method, just a corrected implementation of isOverridden.

            jglick Jesse Glick added a comment - I do not think we need a new API method, just a corrected implementation of isOverridden .

            I suppose I could just check whether base is an interface and then use a different underlying approach from what there is now.

            I probably will add an overload that takes a boolean, to decide whether or not final methods should be considered overrides.

            zastai Tim Van Holder added a comment - I suppose I could just check whether base is an interface and then use a different underlying approach from what there is now. I probably will add an overload that takes a boolean, to decide whether or not final methods should be considered overrides.

            (Also: how do I grab your unit test? Add your repo as a remote and cherry-pick that commit into my branch for a PR?)

            zastai Tim Van Holder added a comment - (Also: how do I grab your unit test? Add your repo as a remote and cherry-pick that commit into my branch for a PR?)
            jglick Jesse Glick added a comment -

            I could just check whether base is an interface

            I think it would suffice to amend Method not found in clazz, let's search in superclasses to also check interfaces in a depth-first recursion. Common idiom in Java reflection.

            add an overload that takes a boolean, to decide whether or not final methods should be considered overrides

            There is no use case for that. final methods should be considered overrides. The intent of the final check was to apply to the method lookup on the base class, not the derived class.

            how do I grab your unit test? Add your repo as a remote

            No need to do that, nor cherry-pick. Just go to your local branch and

            git pull https://github.com/jglick/jenkins isOverridden-JENKINS-62723
            
            jglick Jesse Glick added a comment - I could just check whether base is an interface I think it would suffice to amend Method not found in clazz, let's search in superclasses to also check interfaces in a depth-first recursion. Common idiom in Java reflection. add an overload that takes a boolean, to decide whether or not final methods should be considered overrides There is no use case for that. final methods should be considered overrides. The intent of the final check was to apply to the method lookup on the base class, not the derived class. how do I grab your unit test? Add your repo as a remote No need to do that, nor cherry-pick. Just go to your local branch and git pull https://github.com/jglick/jenkins isOverridden-JENKINS-62723

            Ah that makes sense.

            It's unfortunate that there was/is no guarantee/requirement that base itself declares the method in question, so I do have to keep the lookup-including-base-classes logic for that too.

            zastai Tim Van Holder added a comment - Ah that makes sense. It's unfortunate that there was/is no guarantee/requirement that base itself declares the method in question, so I do have to keep the lookup-including-base-classes logic for that too.

            Going to have to see what happens if for A > B > C, both A and C declare themselves as implementing interface I, while B contains the method override.
            In that case, isOverridden(I, C) should probably still return true.

            So when looking at interfaces (and their super-interfaces) it shouldn't give up when base is encountered, unless it's the last class in the hierarchy implementing that interface.
            So I guess the logic should be: if not found in the current class, get the superclass. If that does not implement base, and base is an interface, go through the interfaces for the current class.

            And abstract methods (for abstract classes implementing an interface) shouldn't be considered overrides either.

            zastai Tim Van Holder added a comment - Going to have to see what happens if for A > B > C, both A and C declare themselves as implementing interface I, while B contains the method override. In that case, isOverridden(I, C) should probably still return true. So when looking at interfaces (and their super-interfaces) it shouldn't give up when base is encountered, unless it's the last class in the hierarchy implementing that interface. So I guess the logic should be: if not found in the current class, get the superclass. If that does not implement base, and base is an interface, go through the interfaces for the current class. And abstract methods (for abstract classes implementing an interface) shouldn't be considered overrides either.

            Added a PR with what should be a fix for this issue.

            Still looking at a further fix for a remaining edge case (where the override for an interface method is provided by a default implementation on a derived interface)

            zastai Tim Van Holder added a comment - Added a PR with what should be a fix for this issue. Still looking at a further fix for a remaining edge case (where the override for an interface method is provided by a default implementation on a derived interface)

            Further fix applied.

            zastai Tim Van Holder added a comment - Further fix applied.

            Fix was merged, should appear in 2.245 early next week.

            zastai Tim Van Holder added a comment - Fix was merged, should appear in 2.245 early next week.
            orgads Orgad Shaneh added a comment -

            Still happens with 2.245.

            orgads Orgad Shaneh added a comment - Still happens with 2.245.
            thoys Thijs Wenker added a comment -

            It seems that it was merged after the 2.245 release. When can we expect the next release with this fix?

            thoys Thijs Wenker added a comment - It seems that it was merged after the 2.245 release. When can we expect the next release with this fix?

            Ah ok, I see that while there was a 2.245 tagged, it was not published as a release at https://github.com/jenkinsci/jenkins/releases/ - so when I checked there to see which version to report here, it looked like 2.245 was still next.

            That means it'll be in 2.246 instead, which will likely get tagged today or tomorrow.

            zastai Tim Van Holder added a comment - Ah ok, I see that while there was a 2.245 tagged, it was not published as a release at https://github.com/jenkinsci/jenkins/releases/ - so when I checked there to see which version to report here, it looked like 2.245 was still next. That means it'll be in 2.246 instead, which will likely get tagged today or tomorrow.
            thoys Thijs Wenker added a comment -

            thoys Thijs Wenker added a comment -
            oleg_nenashev Oleg Nenashev added a comment -

            Released as Jenkins 2.248. Will mark as lts-candidate, just in case we select older version as a new LTS baseline

            oleg_nenashev Oleg Nenashev added a comment - Released as Jenkins 2.248. Will mark as lts-candidate, just in case we select older version as a new LTS baseline

            People

              zastai Tim Van Holder
              webwart H. Feldker
              Votes:
              0 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: