{"id":429,"date":"2026-10-14T08:31:32","date_gmt":"2026-10-14T08:31:32","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2015\/09\/03\/jenkins-java-lang-outofmemoryerror-permgen-space-issues\/"},"modified":"2026-10-14T08:31:32","modified_gmt":"2026-10-14T08:31:32","slug":"jenkins-java-lang-outofmemoryerror-permgen-space-issues","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/jenkins-java-lang-outofmemoryerror-permgen-space-issues\/","title":{"rendered":"Fix Jenkins java.lang.OutOfMemoryError: PermGen Space (Controller, Agents, and Build Tools)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Originally published on 2015-09-03; fully revised and updated.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Jenkins jobs fail with <strong>java.lang.OutOfMemoryError: PermGen space<\/strong>, the practical fix is to apply JVM memory flags in the correct scope: Jenkins controller, Jenkins agent, or the build tool process itself. This walkthrough explains where to set those options on Linux and Windows, how to validate them, and what to do on modern Java versions where PermGen no longer exists.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"400\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2015\/09\/jenkins-java-lang-outofmemo.png\" alt=\"jenkins-java-lang-outofmemoryerror-permgen-space-issues\" class=\"wp-image-3367\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2015\/09\/jenkins-java-lang-outofmemo.png 600w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2015\/09\/jenkins-java-lang-outofmemo-300x200.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">What this Jenkins error usually means<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original error references <strong>PermGen<\/strong>, which applies to older JVMs (typically Java 7 and earlier). In Jenkins environments, failures may come from different JVMs, not only the Jenkins controller process.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Controller JVM:<\/strong> Jenkins service itself runs out of memory.<\/li><li><strong>Agent JVM:<\/strong> build node (SSH\/JNLP\/service) launches with low memory flags.<\/li><li><strong>Build tool JVM:<\/strong> Maven\/Gradle\/Sonar runner process is constrained.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For Java 8 and newer, use Metaspace-related flags instead of PermGen flags.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Triage workflow before changing memory settings<\/h2>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Build fails with OutOfMemoryError] --> B{Failure location}\n    B --> C[Controller logs]\n    B --> D[Agent logs]\n    B --> E[Build tool output]\n    C --> F[Check Java major version]\n    D --> F\n    E --> F\n    F --> G{Java 7 or earlier}\n    G -- yes --> H[Use Xmx and MaxPermSize]\n    G -- no --> I[Use Xmx and MaxMetaspaceSize]\n    H --> J[Apply at controller or agent or tool scope]\n    I --> J\n    J --> K[Restart affected process]\n    K --> L[Re-run build and monitor]\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Where to set JVM options in Jenkins environments<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Configuration point<\/th><th>Scope<\/th><th>When to use<\/th><th>Typical variable\/field<\/th><\/tr><\/thead><tbody><tr><td>OS\/service configuration for Jenkins controller<\/td><td>Jenkins master\/controller JVM<\/td><td>Controller itself crashes or is unstable<\/td><td>JAVA_ARGS or JENKINS_JAVA_OPTIONS<\/td><\/tr><tr><td>Jenkins Global Properties<\/td><td>Environment for jobs<\/td><td>Build steps need memory flags<\/td><td>JAVA_OPTS, GRADLE_OPTS, SONAR_RUNNER_OPTS<\/td><\/tr><tr><td>Node (agent) JVM options<\/td><td>Single agent process<\/td><td>Only specific agents fail with OOM<\/td><td>Node JVM options \/ agent startup arguments<\/td><\/tr><tr><td>Build tool-specific configuration<\/td><td>Maven\/Gradle\/Sonar process<\/td><td>Tool process fails while Jenkins remains healthy<\/td><td>GRADLE_OPTS, MAVEN_OPTS, SONAR_RUNNER_OPTS<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Configuration examples<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Set environment variables in Linux shell profiles<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The original post used <code>~\/.bash_profile<\/code>. Keep in mind this affects only processes that inherit that shell environment.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Java 7 and earlier (PermGen)<\/span>\nexport JAVA_OPTS=<span class=\"hljs-string\">\"-XX:MaxPermSize=512m -Xms512m -Xmx1024m\"<\/span>\nexport GRADLE_OPTS=<span class=\"hljs-string\">\"-XX:MaxPermSize=512m\"<\/span>\nexport SONAR_RUNNER_OPTS=<span class=\"hljs-string\">\"-Xmx512m -XX:MaxPermSize=512m\"<\/span>\n\n<span class=\"hljs-comment\"># Java 8+ (Metaspace)<\/span>\nexport JAVA_OPTS=<span class=\"hljs-string\">\"-Xms512m -Xmx1024m -XX:MaxMetaspaceSize=512m\"<\/span>\nexport GRADLE_OPTS=<span class=\"hljs-string\">\"-Xmx1024m -XX:MaxMetaspaceSize=512m\"<\/span>\nexport SONAR_RUNNER_OPTS=<span class=\"hljs-string\">\"-Xmx512m -XX:MaxMetaspaceSize=512m\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Set controller JVM flags in Jenkins service config<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">From the original guidance: RedHat-based installs often use <code>\/etc\/sysconfig\/jenkins<\/code> and Debian\/Ubuntu installs often use <code>\/etc\/default\/jenkins<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># \/etc\/sysconfig\/jenkins (example)<\/span>\nJENKINS_JAVA_OPTIONS=<span class=\"hljs-string\">\"-XX:MaxPermSize=512m -Xms512m -Xmx1024m\"<\/span>\n\n<span class=\"hljs-comment\"># \/etc\/default\/jenkins (example)<\/span>\nJAVA_ARGS=<span class=\"hljs-string\">\"-XX:MaxPermSize=512m -Xms512m -Xmx1024m\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">If your Jenkins runtime is Java 8 or newer, replace <code>-XX:MaxPermSize<\/code> with a Metaspace limit such as <code>-XX:MaxMetaspaceSize<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Set job environment in Jenkins global configuration<\/h3>\n\n\n\n<ul class=\"wp-block-list\"><li>Go to <strong>Manage Jenkins<\/strong> &rarr; <strong>Configure System<\/strong>.<\/li><li>Under global environment settings, add name\/value pairs such as <code>JAVA_OPTS<\/code> or <code>GRADLE_OPTS<\/code>.<\/li><li>Use this for job-level runtime tools when service-level tuning is not enough.<\/li><\/ul>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTTP\" data-shcb-language-slug=\"http\"><span><code class=\"hljs language-http language-text\"><span class=\"hljs-attribute\">Name<\/span>: JAVA_OPTS\n<span class=\"hljs-attribute\">Value<\/span>: -XX:MaxPermSize=512m -Xms512m -Xmx1024m\n\nName: GRADLE_OPTS\nValue: -XX:MaxPermSize=512m<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTTP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">http<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Agent-specific JVM options (SSH\/JNLP\/Windows service)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Agent configuration depends on launch mode. For Windows JNLP service agents, JVM arguments are commonly set in the agent-side <code>jenkins.xml<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">service<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">id<\/span>&gt;<\/span>jenkins-agent<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">id<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span>&gt;<\/span>Jenkins Agent<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">name<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">arguments<\/span>&gt;<\/span>-jnlpUrl http:\/\/jenkins.example\/computer\/agent\/slave-agent.jnlp -secret ******** -workDir C:\\\\Jenkins<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">arguments<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">executable<\/span>&gt;<\/span>java<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">executable<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">logmode<\/span>&gt;<\/span>rotate<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">logmode<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">onfailure<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"restart\"<\/span>\/&gt;<\/span>\n  <span class=\"hljs-comment\">&lt;!-- Add JVM flags in the executable arguments per your service wrapper format --&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">service<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Verify the applied settings<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After changing options, restart the affected process (controller or agent), then confirm runtime flags from the host.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Confirm Jenkins Java process arguments<\/span>\nps -ef | grep -i jenkins\n\n<span class=\"hljs-comment\"># If jcmd is available, inspect effective JVM flags<\/span>\njcmd $(pgrep -f jenkins | head -n <span class=\"hljs-number\">1<\/span>) VM.flags\n\n<span class=\"hljs-comment\"># Confirm environment options in current shell\/job context<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"$JAVA_OPTS\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"$GRADLE_OPTS\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">References from the original post<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/stackoverflow.com\/questions\/18000841\/jenkins-java-lang-outofmemoryerror-permgen-space\">http:\/\/stackoverflow.com\/questions\/18000841\/jenkins-java-lang-outofmemoryerror-permgen-space<\/a><\/li><li><a href=\"https:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/Builds+failing+with+OutOfMemoryErrors\">https:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/Builds+failing+with+OutOfMemoryErrors<\/a><\/li><li><a href=\"https:\/\/cloudbees.zendesk.com\/hc\/en-us\/articles\/204264000-Why-do-I-receive-java-lang-OutOfMemoryError-PermGen-space\">https:\/\/cloudbees.zendesk.com\/hc\/en-us\/articles\/204264000-Why-do-I-receive-java-lang-OutOfMemoryError-PermGen-space<\/a><\/li><li><a href=\"http:\/\/stackoverflow.com\/questions\/14762162\/how-do-i-give-jenkins-more-heap-space-when-its-running-as-a-daemon-on-ubuntu\">http:\/\/stackoverflow.com\/questions\/14762162\/how-do-i-give-jenkins-more-heap-space-when-its-running-as-a-daemon-on-ubuntu<\/a><\/li><li><a href=\"http:\/\/javarevisited.blogspot.nl\/2011\/09\/javalangoutofmemoryerror-permgen-space.html\">http:\/\/javarevisited.blogspot.nl\/2011\/09\/javalangoutofmemoryerror-permgen-space.html<\/a><\/li><li><a href=\"https:\/\/plumbr.eu\/outofmemoryerror\/permgen-space\">https:\/\/plumbr.eu\/outofmemoryerror\/permgen-space<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Identify <strong>which JVM<\/strong> is failing before increasing memory globally.<\/li><li>Use version-appropriate flags: <strong>PermGen<\/strong> for older JVMs, <strong>Metaspace<\/strong> for Java 8+.<\/li><li>Prefer the <strong>narrowest scope<\/strong> first (specific agent\/tool) before changing controller-wide defaults.<\/li><li>After each change, restart the affected process and verify effective flags from process output.<\/li><li>Track memory changes in configuration management so rollback is easy and consistent across nodes.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Jenkins PermGen errors are usually caused by JVM memory limits set in the wrong place. This guide shows where to configure memory flags for controllers, agents, and build tools, plus how to handle Java 8+ where PermGen was replaced.<\/p>\n","protected":false},"author":1,"featured_media":3367,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[42],"tags":[545,1504,145,1505,1506,1503,1507,593,1509,1508],"class_list":["post-429","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jenkins","tag-how","tag-java-lang-outofmemoryerror-permgen-space","tag-jenkins","tag-jenkins-error","tag-jenkins-issue","tag-jenkins-java-lang-outofmemoryerror-permgen-space","tag-jenkins-space-issue","tag-process","tag-resolve","tag-solution"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/429","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=429"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/429\/revisions"}],"predecessor-version":[{"id":79303,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/429\/revisions\/79303"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3367"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=429"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=429"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}