I came across this error message recently: “The code for the static initializer is exceeding the 65535 bytes limit” while adding supported languages to a localized XPages application. In this post, I’ll explain the cause of the error and a couple of ways to approach fixing it.
Understanding the Error
Every XPage and Custom Control is boils down to a corresponding Java class behind the scenes. You can find these .java
files in Packages Explorer under Local\xsp
.
Each class contains blocks of code for dealing with each component on the page as well as handling localization strings (among other things).
If this file gets too large, it throws the error message above.
The Cause
I’ve never seen this issue until recently, but when I updated a localized application to add 8 more supported languages, this error was thrown for two of the controls.
When I looked into the class files for the controls that threw the error, it was clear what was blowing up the file size — translation strings.
The file builds an array of string arrays in a variable named s_localeStrs
. Below is an example of what it looks like. The first line initializes the variable and then the rest is what is set up for each for the first few things on the page that are translated. (This is from a demo app from Connect 2014.)
private static final String[][] s_localeStrs = new String[][]{ new String[]{ // "" "Hard-Coded Title, Labels, Options", // 0 formTable1/@formTitle "Description", // 1 formTable1/@formDescription "Name", // 2 formRow1/@label "Type", // 3 formRow2/@label }, new String[]{ // de "[de| Hard-Coded Title, Labels, Options ]", // 0 formTable1/@formTitle "[de| Description ]", // 1 formTable1/@formDescription "[de| Name ]", // 2 formRow1/@label "[de| Type ]", // 3 formRow2/@label "[de| Type 1 ]", // 4 comboBox1/xp:selectItem[1]/@itemLabel }, new String[]{ // en_GB "[en_GB| Hard-Coded Title, Labels, Options ]", // 0 formTable1/@formTitle "[en_GB| Description ]", // 1 formTable1/@formDescription "[en_GB| Name ]", // 2 formRow1/@label "[en_GB| Type ]", // 3 formRow2/@label "[en_GB| Type 1 ]", // 4 comboBox1/xp:selectItem[1]/@itemLabel }, new String[]{ // en_IE "[en_IE| Hard-Coded Title, Labels, Options ]", // 0 formTable1/@formTitle "[en_IE| Description ]", // 1 formTable1/@formDescription "[en_IE| Name ]", // 2 formRow1/@label "[en_IE| Type ]", // 3 formRow2/@label "[en_IE| Type 1 ]", // 4 comboBox1/xp:selectItem[1]/@itemLabel }, new String[]{ // lt "LT-Hard-Coded Title, Labels, Options ", // 0 formTable1/@formTitle "LT-Description ", // 1 formTable1/@formDescription "LT-Name ", // 2 formRow1/@label "LT-Type ", // 3 formRow2/@label }, };
As an application is set up to support a language, it adds the string translations for each translated property directly into the class file. So if you support 10 languages, you’ll have 10 sets of strings set up. (Note: this does not happen with translations for computed values that you manage, because the application does not translate them, so it doesn’t mix anything into the page/CC class files.)
This is something you won’t even know or care about for the most part, but when you have a lot of elements on the page to be translated and numerous translations, it can make the size of this class too large, hence the error.
In the case where I saw the error, it was on a custom control that had 864 items to translate. Once the application went from 2 to 10 languages, the size of this java class file got too large.
The Solution
The bottom line is that the class file needs to be cut down to the allowable size. You can do this by breaking the custom control into smaller controls until you get to the right size; then the problem goes away.
However, since that can become quite involved, I recommend doing some analysis on the current control’s design before taking the step to break it up.
Look for ways to modularize/reuse pieces of the page. If there are repetitive controls or combo box option lists, you can look to streamline their usage in order to cut down on the amount of things that are set up for translation.
In this case specifically, there were a bunch of combo boxes on the page with a list of every available time to choose, to the quarter hour. For example: 12:00, 12:15, 12:30, 12:45, 1:00, 1:15, 1:30, and so on.
Each combo box had 48 hard-coded options and there were numerous time fields on the page. This meant that the java class file had a set of 48 strings for each of 10 languages, multiplied by the number of time selection fields on the page. And these are things that don’t need translation! (The same thing could happen for any list of values that wouldn’t need translation, such as a list of proper names like states.)
There are several ways to go about handling this. Here are a few ideas:
- Create the field as a reusable custom control and handle it in one place and then use it as many times as needed
- If the values needed translation, you could set up one list of the values in a custom properties file and refer to it throughout the application.
- If the values don’t need translation, the easiest way to mitigate this issue is to compute the list of choices. Instead of dozens of select item tags, compute it to return an array
- Set up the list of choices once in a configuration/keyword document and look it up either directly from the control
- Define an array in a page-level or scope variable one time and reference it for the combo box’s list of choices as many times as needed
Any of these options modularize the list of options and significantly streamline the page source. They also cut down on a lot of unnecessary elements in the properties files if you need to send them out for translation.
