J2ME "Byte code exceeds 32K" - java

Why i get this error while compiling the Java file in J2ME.
Is it because extensive use of array Objects since i have a lots of array Objects defined in the Java file ?

It might be an array initializer within a method, as in:
void someMethod() {
int[] array = {0, 1, 2, 3};
}
This is equivalent to:
int[] array = new int[4];
array[0] = 0;
array[1] = 1;
array[2] = 2;
array[3] = 3;
and each element assignment takes four VM instructions (between 4 and 12 bytes of code per element.)
If the initializer is too long, it will exceed the 32K limit on the length of a method.

There is restriction with 32KB with method code, note that not with class file size.
Simple code
public void foo() {
int arr[] = {1, 2, 3};
}
will turn into [used javap to obtain this result]
public void foo();
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: iconst_1
6: iastore
7: dup
8: iconst_1
9: iconst_2
10: iastore
11: dup
12: iconst_2
13: iconst_3
14: iastore
15: astore_1
16: return
So you can imagine your huge & ocmplex array would turn into what size.
I suggest that you move your data into external resources in .jar file, it will also compress much better. also try optimizing it

Related

How can I load a reference from a local variable at an index which is unknown at compile time?

As far as I understood the JVM bytecode specification,
aload index pushes a reference found at index onto the current stackframe. In my case, I need to aload a reference found at an index which is stored in a local variable - something like this: aload (iload 2).
(How) Is this possible?
This is not possible. Otherwise verifier would not be able to prove the correctness of the bytecode.
To access values by index use array objects with the corresponding bytecodes, e.g. aaload.
There is no dedicated bytecode instruction to perform this kind of selector, so if you want to load a local variable based on the contents of another variable, you have to code this operation yourself, e.g.
// pick #1 or #2 based on #0 in [0..1]
0: iload_0
1: ifne 8
4: aload_1
5: goto 9
8: aload_2
9: // value is now on the stack, ready for use
or
// pick #1, #2, or #3 based on #0 in [0..2]
0: iload_0
1: ifne 8
4: aload_1
5: goto 18
8: iload_0
9: iconst_1
10: if_icmpne 17
13: aload_2
14: goto 18
17: aload_3
18: // value is now on the stack, ready for use
or, to have a variant that scales with higher numbers of variables:
// pick #1, #2, or #3 based on #0 in [0..2]
0: iload_0
1: tableswitch { // 0 to 2
0: 28
1: 32
2: 36
default: 36
}
28: aload_1
29: goto 37
32: aload_2
33: goto 37
36: aload_3
37: // value is now on the stack, ready for use
The last variant has been generated with the ASM library and the following helper method, calling it like loadDynamic(…, 0, 1, 3);
/**
* Load variable #(firstChoice + value(#selector))
*/
public static void loadDynamic(
MethodVisitor target, int selector, int firstChoice, int numChoices) {
Label[] labels = new Label[numChoices];
for(int ix = 0; ix < numChoices; ix++) labels[ix] = new Label();
Label end = new Label();
target.visitVarInsn(Opcodes.ILOAD, selector);
target.visitTableSwitchInsn(0, numChoices - 1, labels[numChoices - 1], labels);
target.visitLabel(labels[0]);
target.visitVarInsn(Opcodes.ALOAD, firstChoice);
for(int ix = 1; ix < numChoices; ix++) {
target.visitJumpInsn(Opcodes.GOTO, end);
target.visitLabel(labels[ix]);
target.visitVarInsn(Opcodes.ALOAD, firstChoice + ix);
}
target.visitLabel(end); // choosen value is now on the stack
}
Obviously, array based code using the intrinsic index based access instructions is much simpler and more efficient in most cases.

Java memory allocation

I have a question that i have been pondering for a while. Take for instance this particular piece of class
class A{
private static ArrayList<String> listOne;
public Static ArrayList<String> getList()
{
return this.listOne
}
}
Let say i have class B that possess a method to read the details with listOne. To Look through the arraylist, i would need to first get the size of the list in order for my code to know when the arraylist ends. There are 2 ways in which i can do so, one being
int listSize = A.getList().size()
for(int count =0; count < listSize; count++)
{
// code to read through arraylist
}
or i can achieve the same thing with
for(int count=0; count < A.getList().size(); count++)
{
// code to read through arraylist
}
In terms of memory and efficiency, which method is better? Furthermore let says i am reading through a very large array recursively. For simplicity purposes, lets assume that recursively reading through this array would a stack overflow exception. In this situation, would the first method theoretically cause a stack overflow to happen earlier then the second method seeing that each recursive call's stack frame has to keep the state of the variable "listSize"?
Have a look at the result of javap -verbose:
0: invokestatic #2 // Method A.getList:()Ljava/util/ArrayList;
3: invokevirtual #3 // Method java/util/ArrayList.size:()I
6: istore_1
7: iconst_0
8: istore_2
9: iload_2
10: iload_1
11: if_icmpge 27
14: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
17: iload_2
18: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
21: iinc 2, 1
24: goto 9
27: iconst_0
28: istore_2
29: iload_2
30: invokestatic #2 // Method A.getList:()Ljava/util/ArrayList;
33: invokevirtual #3 // Method java/util/ArrayList.size:()I
36: if_icmpge 52
39: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
42: iload_2
43: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
46: iinc 2, 1
49: goto 29
52: return
First case is:
9: iload_2
10: iload_1
11: if_icmpge 27
14: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
17: iload_2
18: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
21: iinc 2, 1
24: goto 9
And the second one:
29: iload_2
30: invokestatic #2 // Method A.getList:()Ljava/util/ArrayList;
33: invokevirtual #3 // Method java/util/ArrayList.size:()I
36: if_icmpge 52
39: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
42: iload_2
43: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
46: iinc 2, 1
49: goto 29
As you can see, it will get the list and its size during each loop iteration.
But, this might be optimized by JIT, so the result is not obvious from just the compiled bytecode.
Created from:
import java.io.*;
import java.util.*;
public class Z {
public static void main(String[] args) throws Exception {
int listSize = A.getList().size();
for(int count =0; count < listSize; count++) {
System.out.println(count);
}
for(int count =0; count < A.getList().size(); count++) {
System.out.println(count);
}
}
}
class A{
private static ArrayList<String> listOne = new ArrayList<>(Arrays.asList("1", "2", "3"));
public static ArrayList<String> getList()
{
return listOne;
}
}
Both the loop are same. Second one is better coding as it reduces line of code.
Since you mentioned that your need is to traverse the list it is much better to use the enhanced (for-each) for loop.
What are the Advantages of Enhanced for loop and Iterator in Java?
why is enhanced for loop efficient than normal for loop
Regarding which of the method is more efficient, I think they won't have any noticeable differences. And depending on the JVM, like Germann has said, the compiler will even optimize this. So just don't worry about this negligible difference.
I personally will use the second method since it has fewer lines of code and I'm lazy...
However, why not use neither?
There's a super cool alternative, and its name is... JON CENA The enhanced for loop.
Let's compare it with a normal for loop:
Normal:
for (int i = 0 ; i < A.getList().size() ; i++ {
}
Enhanced:
for (String item : A.getList()) {
// Instead of using A.getList().get(i) to access the items, just use "item"!
}
Look how nice it is!
The major difference between these two for loops is that
The normal for loop is just a kind of a while loop with initialization and incrementation.
The enhanced for loop calls .iterator().hasNext() and .iterator().next() to loop.
You need to know the size of the list to use a normal for loop
Your list just needs to implement Iterable and probably Iterator to use an enhanced for loop. No size is needed.
An enhanced for loop has the following limitations:
You can't loop through two arrays at the same time
It's better to use a normal for loop if you want to know the index of the list, since calling indexOf a lot of times is not very efficient.

Does using an intermediate variable instead of array.length make your for-loop faster?

The "Performance Tips" section in the Android documentation has a pretty bold claim:
one() is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.
where it refers to this code snippet:
int len = localArray.length;
for (int i = 0; i < len; ++i) {
sum += localArray[i].mSplat;
}
This surprised me a lot because localArray.length is just accessing an integer and if you'd use an intermediate variable, you'd have to do that exact same step again. Are we really saying that an intermediate variable that only has to go to x instead of y.x is faster?
I took a look over at this question which is about the same idea but uses an arraylist and its subsequent .size() method instead. Here the concensus seemed to be that there would be no difference since that method call is probably just going to be inlined to an integer access anyway (which is exactly the scenario we have here).
So I took to the bytecode to see if that could tell me anything.
Given the following source code:
public void MethodOne() {
int[] arr = new int[5];
for (int i = 0; i < arr.length; i++) { }
}
public void MethodTwo() {
int[] arr = new int[5];
int len = arr.length;
for (int i = 0; i < len; i++) { }
}
I get the following bytecode:
public void MethodOne();
Code:
0: iconst_5
1: newarray int
3: astore_1
4: iconst_0
5: istore_2
6: iload_2
7: aload_1
8: arraylength
9: if_icmpge 18
12: iinc 2, 1
15: goto 6
18: return
public void MethodTwo();
Code:
0: iconst_5
1: newarray int
3: astore_1
4: aload_1
5: arraylength
6: istore_2
7: iconst_0
8: istore_3
9: iload_3
10: iload_2
11: if_icmpge 20
14: iinc 3, 1
17: goto 9
20: return
They differ in the following instructions:
Method one
6: iload_2
7: aload_1
8: arraylength
9: if_icmpge 18
12: iinc 2, 1
15: goto 6
18: return
Method two
9: iload_3
10: iload_2
11: if_icmpge 20
14: iinc 3, 1
17: goto 9
20: return
Now, I'm not 100% sure how I have to interpret 8: arraylength but I think that just indicates the field you're accessing. The first method loads the index counter and the array and accesses the arraylength field while the second method loads the index counter and the intermediate variable.
I benchmarked the two methods as well with JMH (10 warmups, 10 iterations, 5 forks) which gives me the following benchmarking result:
c.m.m.Start.MethodOne thrpt 50 3447184.351 19973.900 ops/ms
c.m.m.Start.MethodTwo thrpt 50 3435112.281 32639.755 ops/ms
which tells me that the difference is negligible to inexistant.
On what is the Android documentation's claim that using an intermediate variable in a loop condition, based?
You misunderstood the documentation. They are not referring to what you have described (although I don't blame you, they should've put more effort into those docs :)).
It pulls everything out into local variables, avoiding the lookups.
By avoiding the lookups they refer to field vs local variable access cost. Accessing the field (mArray in the example in the docs) requires loading this first, then loading the field based on the fixed offset from this.
After a while, JIT will probably figure out what's going on and optimize the field access as well (if the field is not volatile or some other form of synchronization happens in the loop) and rewrite the code so that all of the variables participating in the loop are accessed/changed in the CPU registers and caches until the end of the loop.
Generally, it could be potentially much more work for JIT to figure out whether it is safe to optimize the access to the length of the array referenced from a field compared to the reference stored in a local variable. Let's say we have the following loop:
for (int i = 0; i < array.length; ++i) {
process(array[i]);
}
If array is a field and process invokes thousands of lines of complex code, then JIT may find it difficult to check whether the array field is changed somewhere in the loop to reference some other array which has a different length.
Obviously, it is much easier to check whether the local variable is changed in this case (three lines of code).
Actually no it didn't make the loop faster, your idea is right when using the String.length()
the difference is that
array.length is just a field which have a value that you just use it directly..
String.length() is a method which need a time to be executed.

How are array object created when using a bracketed list

I understand an array object in Java is created when I call its constructor with the new keyword:
int[] myIntArray = new int[3];
But if I instead write
int[] myIntArray = {1,2,3};
an array object gets created, but I haven't called its constructor with new. How does this work under the hood - how can an object be created in Java without calling the constructor?
As far as creating the array object is concerned, it's syntactic sugar. When compiled, it works exactly like the standard syntax.
The difference here though is that with the first version, you aren't populating the array - all elements are the default value for int, which is zero.
With the second version, you're creating, and populating the array.
This part:
{1,2,3}
is an array initializer that can be used as part of a declaration. To quote the JLS, section 10.6:
An array initializer may be specified in a declaration (§8.3, §9.3,
§14.4), or as part of an array creation expression (§15.10), to create
an array and provide some initial values.
ArrayInitializer:
{ VariableInitializersopt ,opt }
The first version populates an integer array with the default 0 value. The second assigns values explicitly.
The first version is equivalent to
int[] myIntArray = {0, 0, 0};
while the second is the same as
int[] myIntArray = new int[] {1,2,3};
The new keyword is only mandatory for non declarative statements, for example .
int[] myIntArray;
myIntArray = new int[] {1,2,3};
Datatypes
Arrays
Both statements are same. The second statement int[] myIntArray = {1,2,3}; is short cut to syntax using new method.
int[] myIntArray ={1,2,3} , this case length of the array is determined by the number of values provided between braces and separated by commas.
Take this code and compile it:
public class ArrayTest {
public static void main1() {
int[] array = new int[3]; array[0] = 10; array[1] = 20; array[3] = 30;
}
public static void main2() {
int[] array = new int[] {10, 20, 30};
}
public static void main3() {
int[] array = {10, 20, 30};
}
}
Then use javap -c to disassemble it to view its bytecode to get the following results. But what you will is that the later two snippets or methods compile to the same bytecode. So int[] array = new int[] {1, 2, 3} and int[] array = {1, 2, 3} are the same. But seperately creating an array and assigning values to each of its element is treated differently and so the later two snippets are not syntactic sugar for the first snippet.
$ javap -c ArrayTest
Compiled from "ArrayTest.java"
public class ArrayTest extends java.lang.Object{
public ArrayTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main1();
Code:
0: iconst_3
1: newarray int
3: astore_0
4: aload_0
5: iconst_0
6: bipush 10
8: iastore
9: aload_0
10: iconst_1
11: bipush 20
13: iastore
14: aload_0
15: iconst_3
16: bipush 30
18: iastore
19: return
public static void main2();
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: bipush 10
7: iastore
8: dup
9: iconst_1
10: bipush 20
12: iastore
13: dup
14: iconst_2
15: bipush 30
17: iastore
18: astore_0
19: return
public static void main3();
Code:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: bipush 10
7: iastore
8: dup
9: iconst_1
10: bipush 20
12: iastore
13: dup
14: iconst_2
15: bipush 30
17: iastore
18: astore_0
19: return
Under the hood, both ways of initializing an array is the same.
For another example, look at this:
String str = "Hello"; // no 'new' statement here
String str = new String("Hello");
Both statements do the same thing, but one is far more convenient than the other. But under the hood, they pretty much do the same thing after compilation.

How Does Java Know How to Iterate an Array

String[] strs = new String[] { "1", "2", ... , "6" };
for (String s : strs) {
System.out.println(s);
}
This is a question about java internals.
In the above code sample, how does the foreach loop figure out how long the array is? Are arrays actually objects internally or is it using stuff like sizeof that is inaccessible to front end programmers?
I have a feeling I'm just missing something stupid, but I figure it could also be cool. :-)
I compiled the following code:
public class ArrayIterator
{
public static void main(String[] argv)
{
String[] strs = new String[] { "1", "2", "3", "4", "5" };
enhancedPrint(strs);
normalPrint(strs);
}
public static void enhancedPrint( String[] strs )
{
for (String s : strs)
{
System.out.println(s);
}
}
public static void normalPrint( String[] strs )
{
String[] localArray = strs;
int len = localArray.length;
for (int i = 0; i < len; i++)
{
String s = localArray[i];
System.out.println(s);
}
}
}
This is the disassembled (javap -c ArrayIterator) bytecode for the iterating functions:
The enhanced print:
public static void enhancedPrint(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return
A normal for loop:
public static void normalPrint(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #10; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #11; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return
As you can see, in both cases, the compiler is loading the arrays length (strs.length) and looping against it. We see that the enhanced for-each loop, in the case of an Array is syntactic sugar for looping against the array's length (rather than in an Object's case where it uses an Iterator).
I have edited the 'normal' for loop such that it is much less idiomatic, but that it has the same bytecode as the enhanced for loop. For all intents and purposes, the normal for loop version is what the compiler generates when it compiles the enhanced for each loop.
Yes, there is something akin to the C++ sizeof operator -- it's the length instance variable (which gives the number of elements in the array, not the size in bytes.) The length field is always a public member of the array, so it is accessible to Java programmers.
And yes, arrays are objects, and not just internally.
(More broadly, the for loop syntax works as described in the question that org.life.java linked to; but that isn't quite what you were asking.)
Yes, arrays are objects with a "length" field. Java Language Specification: http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#64347

Categories

Resources