From time to time the error message GEN_BRANCHOFFSET_LIMIT_REACHED pops up. It is a very complex problem right from the heart of the ABAP VM. Let us look quickly at why it happens and some ideas to work around the problem. No, there is no patch for this problem.
Any (most?) computer languages have typical limitations that play a role in code generation. The ABAP VM is not exception in this case. One such an limitation is that one IF-statement can only jump 32KB of byte code. So effectively, the source code between the IF- and ENDIF-statements, when compiled, must not be more than 32KB of byte code.
And this plays a big role when the Layout of a BSP page is compiled. (The same rules applies for BSP views as well.) For each BSP page, an ABAP class is generated (in the temporary package $TMP). The name is very criptic, as it constructed from with a GUID (global unique identifier). For example: CL_O2D7QDB5488MACT6YI2S549GQVB.
In the generated class, for the complete layout, source code is generated into one method. The event handlers (OnCreate, OnInitialization, etc) are also placed into separate methods on the same class. In this way, each BSP page is translated into a self contained ABAP class, that is generated and instantiated in one step.
So what the problem effectively states, is that somewhere within a method, there is an IF-statement that has a body that exceeds the jump limitations of the ABAP VM. To understand the problem better, we have to look a little bit at how source code generation is done in BSP.
BSP Source Code Generation
Let us assume a simple BSP page with the following source code:
This program shows one technique how an IF-statement can appear within the generated source code. The complete source code (in slightly abstract format) will be:
The very first interesting aspect is that all static HTML in the BSP page is stored separately in the database, and dynamically loaded at runtime into one string (
_m_html). Any static HTML sequence, independent of length, is translated into print statement.
ABAP code within the BSP page is emitted verbatim. BSP print sequences (
<%=...%>) are translated to code that first forces the value to a string (effectively using ABAP assign statement), and then just prints the string.
In this example, the generated source code reflects very much the source code that was written on the BSP page, and there is a relationship between the length of the written layout code and the generated source code.
Let us look at a slightly more complex example, where a few BSP tags are used on a page:
This simplest of simple examples, already generate rather complex code. The reason for this is in the specification of the BSP elements themselves. To allow a flexible architecture, BSP elements can dynamically decide a number of aspects. First, let us look at the generated source for the example (extremely stripped!):
The complexity of this source code comes from the fact that the BSP compiler does not know before hand whether a specific BSP element wishes to process its own body (inner BSP elements), or wish to just over the body. The BSP element can decide this during its DO_AT_BEGINNING( ) method. Therefor the BSP compiler generates the IF-statements to test for this condition.
The use of BSP elements is the second source of IF-statements on a BSP page.
Effectively the problem is that the complete layout of one BSP page is placed into one method in a class. And this method now has in its generated form an IF statement that is too large. Any solution must attempt to remove some code from the generated method (which means directly from the layout) and place it somewhere else. Below are three typical approaches that are recommended.
Solution Idea: Use Class Methods to Reduce Layout Code
Probably the simplest technique would be to strip code from the layout of the BSP page, and to place it into a method of class.
Very important: Long sequences of HTML on a page does not make much of a difference in the generated source of the method. The complete HTML sequence is replaced with out
print_string statement to start at a an offset and dump the string for a specific length.
For such work, one should look at large blocks of program code (
<%...%> sequences), or for large blocks of print code (
<%= .. %>). Each of these interrupts the HTML, which causes the
print_string statement to be splitted into a large number of
print_string statements. See the first code generation example above. Let us examine this example code again:
What we see is that the
<%IF...%> sequence, and the
<%=sy-uname%> causes many more
print_string statements to be emitted, which contributes significantly to the generated code in the layout method.
One solution would be to place this critical code sequence in a separate method. Then the layout code would reduce to:
In the above coding,
greeting is a method that has a returning parameter of type string. This string is then printed. The method itself would be:
Solution Idea: Use Smaller Views in MVC to Split Layout Code
The use of methods to contain rendering code works well with HTML code, but comes more complex once BSP extensions are used. Although it is possible process BSP elements inside methods, it is not easy to write and main. Recommended is to split large layouts into separate views. One typical example could be to place the content of each tab in a tabstrip onto a separate view.
Let us start with this example again, with the goal to place the
<form> and its content onto a separate view:
As a first step we create a new view (called
my_view.htm) with the displaced content (cut-and-paste from page to view):
On the page main page (or view!), place now a call to a controller that will embed the view. Keep in mind it is not possible to directly expand views in place. See also that we have now added the BSP extension "BSP".
As a last step, we create a new controller (
my_controller.do). We add one attribute
view TYPE string and implement the
Passing parameters to different views can also easily be done via the controller.
- MVC Documentation
- The BSP example application IT05 uses the above simple controller to embed any number of views.
Solution Idea: Use BSP Element Composition to Bundle BSP Elements
The most complex, but also the most rewarding approach, is to group often used BSP elements (must be more than one) into one BSP element. The generated code is dramatically reduced, as only one BSP element is called inline. This BSP element will then process/expand all the other BSP elements that it contain.
This technique is especially of interest when a sequence of BSP elements are used often, typical example could be the sequence
<htmlb:label><htmlb:inputField>. For more complete information, please refer to the recommended documentation.
- Defining Your Own BSP Extension
- Creating a New BSP Extension with Composite Elements
- See the BSP-element
<htmlb:page>, implemented in class
CL_HTMLB_PAGE. This BSP element processes the complete
<htmlb:document*>family of BSP elements in one step.
Solution Idea: Replace BSP Element Sequences with Light-Weight Sequences
Often BSP elements are just wrappers around simple HTML sequences. However, we have seen that such BSP elements can cause a large explosion in the generated code. The use of the BSP elements are practical, as the BSP compiler will help to valid that large sequences are correctly nested. However, in cases where the generated source code is to large, ir might help to replace a few of these sequences with native code.
Let us assume this typical form layout example:
<htmlb:gridLayoutCell> tags dominate the code generation, but in the final emited HTML, only reduces to effectively a
<table> sequence. In cases where the generated source code is to large, consider to replace the BSP elements with native HTML code. The example code would then be:
From written code in the layout section, this sequence has about the same complexity. However, each sequence of HTML reduces to one line of generated source code, whereas each BSP element used will reduce to a large number of lines of generated source code.
The alternative could be to replace the
<htmlb:gridLayout> with the newer
<phtmlb:matrix>. This new BSP element uses new features from the BSP compiler to dramatically reduce the generated code footprint. The internal "cell" tags are not separate BSP elements for which code must be generated, but are simple inline method calls onto the
<phtmlb:matrix> BSP element. This effectively reduces the number of BSP elements for which code must be generated by a large factor.
The example could then be (notice the use of the PHTMLB library):