JConsole to the Rescue
A few months back I ran into this error Java.lang.OutOfMemoryError: PermGen space while working on some ODI integrations. I pulled up a quick google search and found the second link of the list was stackoverflow bam problem resolved. Well that was in Development.
Then couple weeks ago I was migrating to the Test and again I ran into Java.lang.OutOfMemoryError: PermGen space knowing that I already fixed it development it didn't take me long to make the change in the Test environment. I even took the time to make the fix a little more pretty by making a change to the odiparams.bat file.
I added the following:
- set ODI_MAX_PERM=512m
- set ODI_ADDITIONAL_JAVA_OPTIONS=-XX:MaxPermSize=%ODI_MAX_PERM% %ODI_ADDITIONAL_JAVA_OPTIONS%
REM # REM # Other Parameters REM # set ODI_INIT_HEAP=1G set ODI_MAX_HEAP=2G set ODI_JMX_PROTOCOL=rmi set ODI_MAX_PERM=512m set ODI_ADDITIONAL_JAVA_OPTIONS=-XX:MaxPermSize=%ODI_MAX_PERM% %ODI_ADDITIONAL_JAVA_OPTIONS%
With Test working great we are ready to move to Production, time to get IT involved since I can't touch these servers. Everything is going smooth until I went to run one of the larger integrations I have. Then BAM Java.lang.OutOfMemoryError: PermGen space. WTH?! I had IT do the modification to the odiparmas.bat I watched them do it. I even watched them restart it.
Maybe something is different with the full data set, lets bump my settings up, nope still not working. Someone suggests that I migrate code in addition to scenarios. I know I shouldn't but from the application side that's the only difference so I burn a few days migrating code to production. Oddly enough the process progresses farther into integration running from source instead of scenario but it still fails on the last step... the status email.
Well lets have IT open an SR, Oracle comes back with "Well your code must be looping and/or creating a objects and not releasing them". Ok so I checked my Jython, found a spot or two where I could have helped the JVM more easily determine where memory could reclaimed by me setting the value to None. Let's give that a shot... damn you PermGen! Ok well let's take a look at the KMs that come with ODI... same as my code could be a smidge better but no smoking gun.
I generally try not to open an SR as I normally figure out the issue on my own rather quickly. I've wasted many of countless hours on the phone with support (Oracle, Microsoft, Etc.) only to resolve an issue or develop a workaround myself. Since I don't have direct access to the server this wasn't one of those times.
Laura D. (thank you!) from Oracle Support in addition to identifying some of the code issues I had suggested we use JConsole or JVisualVM to monitor ODI. So with the help of IT we modified the odiparams.bat file and add the following options.
REM # REM # Additional Java Options REM # set ODI_ADDITIONAL_JAVA_OPTIONS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
We then restarted the ODI agent (standalone) using the agent bat file to run it in the foreground and executed JConsole (X:\Oracle\Middleware\jdk160_35\bin).
JConsole found the process ODI was running in and allowed us to attach to it.
We kicked off the integration and then browsed around JConsole for a few minutes before discovering the VM Summary tab.
And that is were we noticed that VM Arguments that were passed to the ODI agent in the Production environment for some reason were missing -XX:MaxPermSize=512m. So I asked IT to copy the lower half of the odiparams.bat file from Test and restart the ODI Agent. We looked again in JConsole, this time the argument was set so we ran the integration... Success!
I should have guessed that this was the problem, I had a feeling it was but I was sure how to see what was being set for the JVM. Luckily oracle provides some nice tools for seeing what's going on inside the application and It looks like JVisualVM can get even more details than JConsole.