rp346
rp346

Reputation: 7048

Jenkinsfile : java.lang.RuntimeException: Method code too large

I have Jenkins Pipeline code in jenkisnfile which is 790 lines. I am getting following error message Method code too large

11:05:24  org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
11:05:24  General error during class generation: Method code too large!
11:05:24  
11:05:24  java.lang.RuntimeException: Method code too large!
11:05:24    at groovyjarjarasm.asm.MethodWriter.a(Unknown Source)
11:05:24    at groovyjarjarasm.asm.ClassWriter.toByteArray(Unknown Source)
11:05:24    at org.codehaus.groovy.control.CompilationUnit$17.call(CompilationUnit.java:827)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1065)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
11:05:24    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
11:05:24    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
11:05:24    at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
11:05:24    at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:571)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:523)
11:05:24    at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:337)
11:05:24    at hudson.model.ResourceController.execute(ResourceController.java:97)
11:05:24    at hudson.model.Executor.run(Executor.java:429)
11:05:24  
11:05:24  1 error
11:05:24  
11:05:24    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1085)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
11:05:24    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
11:05:24    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
11:05:24    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
11:05:24    at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
11:05:24    at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:571)
11:05:24    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:523)
11:05:24    at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:337)
11:05:24    at hudson.model.ResourceController.execute(ResourceController.java:97)
11:05:24    at hudson.model.Executor.run(Executor.java:429)
11:05:24  Finished: FAILURE

Using following versions
OS : Ubuntu 18.04.1
Jenkins : 2.263.4
Java : 1.8.0_181 ( Master & Slave )
Set JAVA_ARGS="-Xmx2048m" in /etc/default/jenkins( Master )

How can I fix this ?

Upvotes: 6

Views: 21886

Answers (3)

DamonWu
DamonWu

Reputation: 134

According my recent experience on this Jenkins issue, I would like top share my current approach which is working for my case:

File name: shellScripts.groovy

def call(Map parameters = [:]) {
  // ... other groovy function ...

  def blockOfShellScriptsCodeLogic = {
    // ... YOUR CUSTOMISED SHELL COMMANDS ... 
    // For example:
    sh 'shell commend one'
    sh 'shell commend two'
  }

  // ... other groovy function ...
}

return [
  // ... other definitions ...
  blockOfShellScriptsCodeLogic: blockOfShellScriptsCodeLogic
]

And then, when we go to the pipeline file which contains pipeline {}, for example, we can do something like this:

File name: runPipeline.groovy

def call(Map parameters = [:]) {
  // ... other sections ...

  pipeline {
    def runShellScripts = shellScripts() // because above groovy file is named as shellScripts

    environment { ... }
    agent { ... }
    
    stages {
      stage('YOUR STAGE NAME') {
        steps {
          container('docker') { // any container, this is just an example, eg: we can use Jenkins docker container
            script {
              runShellScripts.blockOfShellScriptsCodeLogic()
            }
          }
        }
      }
    }

    // ...
    
    post { ... }
  }

  // ... other sections ...
}

Please refer to this reference which is really good: Reference Article

Upvotes: 0

Altaf
Altaf

Reputation: 3076

Yes, this is a limitation and you must use shared libraries/ divide them into methods to fix this. Reference for shared libraries: https://www.jenkins.io/doc/book/pipeline/shared-libraries/

Solution: Use your jenkinsfile for defining stages and all methods/functionalities are implemented in shared library which will just be called from your jenkinsfile.

Example implemenation as shown below. Create a file named : sharedlibraries (groovy file)

#!groovy
// Write or add Functions(definitions of stages) which will be called from your jenkins file
def Create_AMI(PROJECT_NAME, ENV_NAME)
 {
     echo ENV_NAME
     sh "packer build jenkins/${PROJECT_NAME}/${PROJECT_NAME}-ami.json"
     // You can also set the environment below example:
     env.ENV_NAME ="dev"
 }

return this

In your Jenkinsfile write below code:

// Global variable is used to get data from groovy file(shared library)
def stagelibrary
stage('Create New AMI') {   
            steps {
              script {
                        // Load Shared library Groovy file stagelibraries.Give your path of stagelibraries file whic is created
                        stagelibrary = load 'C:\\Jenkins\\stagelibraries'
                        // Execute Create_AMI function. You can add if else conditions over here, based on your branches. But am not sure of your conditions.
                        // You can also pass your environment variable 
                        // in the Crete_AMI function using env.<YOURENVVARIABLE>
                        stagelibrary.Create_AMI(PROJECT_NAME,env.ENV_NAME)       
                      }               
                  }
        }

This was just an example to show you how you can divide your functionality into sharedlibraries and which will not give you error related to code limit.

Upvotes: 6

jjhickmon
jjhickmon

Reputation: 116

Java has a 64K size limit on bytecode. It is not an issue with Jenkins. To solve this, you should break apart your pipeline into methods. There is a great example here.

Upvotes: 10

Related Questions