Related
Is there any maximum size for code in Java? I wrote a function with more than 10,000 lines. Actually, each line assigns a value to an array variable.
arts_bag[10792]="newyorkartworld";
arts_bag[10793]="leningradschool";
arts_bag[10794]="mailart";
arts_bag[10795]="artspan";
arts_bag[10796]="watercolor";
arts_bag[10797]="sculptures";
arts_bag[10798]="stonesculpture";
And while compiling, I get this error: code too large
How do I overcome this?
A single method in a Java class may be at most 64KB of bytecode.
But you should clean this up!
Use .properties file to store this data, and load it via java.util.Properties
You can do this by placing the .properties file on your classpath, and use:
Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
There is a 64K byte-code size limit on a method
Having said that, I have to agree w/Richard; why do you need a method that large? Given the example in the OP, a properties file should suffice ... or even a database if required.
According to the Java Virtual Machine specification, the code of a method must not be bigger than 65536 bytes:
The value of the code_length item gives the number of bytes in the code array for this method.
The value of code_length must be greater than zero (as the code array must not be empty) and less than 65536.
code_length defines the size of the code[] attribute which contains the actual bytecode of a method:
The code array gives the actual bytes of Java Virtual Machine code that implement the method.
This seems a bit like madness. Can you not initialize the array by reading the values from a text file, or some other data source?
This error sometimes occur due to too large code in a single function...
To solve that error, split that function in multiple functions, like
//Too large code function
private void mySingleFunction(){
.
.
2000 lines of code
}
//To solve the problem
private void mySingleFunction_1(){
.
.
500 lines of code
}
private void mySingleFunction_2(){
.
.
500 lines of code
}
private void mySingleFunction_3(){
.
.
500 lines of code
}
private void mySingleFunction_4(){
.
.
500 lines of code
}
private void MySingleFunction(){
mySingleFunction_1();
mySingleFunction_2();
mySingleFunction_3();
mySingleFunction_4();
}
Try to refactor your code. There is limit on the size of method in Java.
As mentioned in other answers there is a 64KB of bytecode limit for a method (at least in Sun's java compiler)
Too me it would make more sense to break that method up into more methods - each assigning certain related stuff to the array (might make more sense to use a ArrayList to do this)
for example:
public void addArrayItems()
{
addSculptureItems(list);
...
}
public void addSculptureItems(ArrayList list)
{
list.add("sculptures");
list.add("stonesculpture");
}
Alternatively you could load the items from a static resource if they are fixed like from a properties file
I have run into this problem myself. The solution that worked for me was to refactor and shrink the method to more manageable pieces. Like you, I am dealing with a nearly 10K line method. However, with the use of static variables as well as smaller modular functions, the problem was resolved.
Seems there would be a better workaround, but using Java 8, there is none...
I came to this question because I was trying to solve a similar problem. I wanted to hard code a graph that had 1600 elements into a 2D integer array for performance reasons. I was solving a problem on a leetcode style website and loading the graph data from a file was not an option. The entire graph exceeded the 64K maximum so I could not do a single static run of assignments. I split the assignments across several static methods each below the limit and then called each method one by one.
private static int[][] G = new int[1601][];
static {
assignFirst250();
assignSecond250();
assignSecond500();
assignThird500();
}
private static void assignFirst250() {
G[1] = new int[]{3,8,15,24,35,48,63,80,99,120,143,168,195,224,255,288,323,360,399,440,483,528,575,624,675,728,783,840,899,960,1023,1088,1155,1224,1295,1368,1443,1520,1599};
G[2] = new int[]{2,7,14,23,34,47,62,79,98,119,142,167,194,223,254,287,322,359,398,439,482,527,574,623,674,727,782,839,898,959,1022,1087,1154,1223,1294,1367,1442,1519,1598};
You can add another method to create space for your code for additional data space, you might have a method that is taking a large amount of data space. Try dividing your methods because I had the same issue and and fix it by creating another an additional method for the same data in my java Android code, The issue was gone after I did that.
I have an enum that causes the .java file to be over 500KB in size. Eclipse can build it for some reason; the eclipse-exported ant build.xml cannot. I'm looking into this and will update this post.
this is due to all code in single methods
solution :create more some small methods then this error will be gone
As there is a size limit for methods and you don't want to redesign your code as this moment, may be you can split the array into 4-5 parts and then put them into different methods. At the time of reading the array, call all the methods in a series. You may maintain a counter as well to know how many indexes you have parsed.
ok maybe this answer is too late but I think this way is better than another way so
for example, we have 1000 rows data in code
break them
private void rows500() {
//you shoud write 1-500 rows here
}
private void rows1000() {
you shoud write 500-1000 rows here
}
for better performance put an "if" in your codes
if (count < 500) {
rows500();
} else if (count > 500) {
rows1000();
}
I hope this code helps you
I am relatively new to using the netcdf-java library, and I've immediately run into a problem when trying to load a file. The problem is that there doesn't seem to be a way to load a NetcdfFile from a byte array stored in memory, and that is the base form of my data. To elaborate a little, it is actually a .cdf file uploaded through a client, which the client then converts into a byte array for the server code to read. So the server, where my code is running, cannot see the uploaded file at all. I also cannot assume the server itself is writable, so essentially there is no "location" to pass into the typical NetcdfFile loading methods.
The FAQ on ucar.edu does mention the possibility of reading from a non-file source, here. It says I should write my own IOSP, which I am happy to do. However, there is very little guidance on how to do this.
I don't know how to implement isValidFile when the only thing passed into the function is a RandomAccessFile, which the FAQ says can be ignored.
I don't know how my IOSP will obtain the byte array in question for use in readData.
I don't know why the minimal example in the FAQ advises me to make a new NetcdfFile class, when it seems I could just use the default one but pass in my custom IOSP.
This question is a little vague, but I am truly lost without many clues on where to even begin. Any guidance would be appreciated.
EDIT: I'm using 5.4.2 of the netcdf-java library.
I found this answer in the support archives. The solution is to use InMemoryRandomAccessFile. The constructor takes a String location and a byte array containing the file's contents. From my testing, I think the location can be any arbitrary string. Here is the code that worked for me.
byte[] filebytes = retrieveFileBytes(clientFilepath);
InMemoryRandomAccessFile raf = new InMemoryRandomAccessFile(clientFilepath, filebytes);
NetcdfFile file = NetcdfFiles.open(raf, clientFilepath, null, null);
Variable peakRetentionTime = file.findVariable("peak_retention_time");
if (peakRetentionTime == null) {
displayWarning("peak_retention_time null!");
} else {
Array data = peakRetentionTime.read();
displayInfo(Ncdump.printArray(data));
}
The following Code describes my problem:
private void transact(TreeSet<BankmanagerTransaction> set) {
BankmanagerTransaction transaction;
while(!set.isEmpty()) {
transaction = set.first();
execute(transaction);
printBalance(transaction);
printLedger(transaction);
printJustifiedLedger(transaction);
}
}
Every print function prints to a different File. So I'm wondering what's best practice here.
Is it better to build string and then at the end of the transact method print everything at once, or write to the file line by line?
To make more clear what I'm trying to get at, is the time the file is being edited and therfore used by the program. Because as far as I'm aware I'd have to create a Writer for each file in the transact method and pass it to each of the 3 methods everytime.
In the most cases it's the same, but...
Your answer should change with different critereria, i.e. max String length is limited by ram, so in very very lenght cases it is better to write line by line.
But everytime you write (and flush), you are accessing the disk. In remote file locations, if the connection is very unreliable or you have latency, you can build an entire String and write once.
It depends by what is your situation, in general try to make your code CLEAR.
Is there any maximum size for code in Java? I wrote a function with more than 10,000 lines. Actually, each line assigns a value to an array variable.
arts_bag[10792]="newyorkartworld";
arts_bag[10793]="leningradschool";
arts_bag[10794]="mailart";
arts_bag[10795]="artspan";
arts_bag[10796]="watercolor";
arts_bag[10797]="sculptures";
arts_bag[10798]="stonesculpture";
And while compiling, I get this error: code too large
How do I overcome this?
A single method in a Java class may be at most 64KB of bytecode.
But you should clean this up!
Use .properties file to store this data, and load it via java.util.Properties
You can do this by placing the .properties file on your classpath, and use:
Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("yourfile.properties");
properties.load(inputStream);
There is a 64K byte-code size limit on a method
Having said that, I have to agree w/Richard; why do you need a method that large? Given the example in the OP, a properties file should suffice ... or even a database if required.
According to the Java Virtual Machine specification, the code of a method must not be bigger than 65536 bytes:
The value of the code_length item gives the number of bytes in the code array for this method.
The value of code_length must be greater than zero (as the code array must not be empty) and less than 65536.
code_length defines the size of the code[] attribute which contains the actual bytecode of a method:
The code array gives the actual bytes of Java Virtual Machine code that implement the method.
This seems a bit like madness. Can you not initialize the array by reading the values from a text file, or some other data source?
This error sometimes occur due to too large code in a single function...
To solve that error, split that function in multiple functions, like
//Too large code function
private void mySingleFunction(){
.
.
2000 lines of code
}
//To solve the problem
private void mySingleFunction_1(){
.
.
500 lines of code
}
private void mySingleFunction_2(){
.
.
500 lines of code
}
private void mySingleFunction_3(){
.
.
500 lines of code
}
private void mySingleFunction_4(){
.
.
500 lines of code
}
private void MySingleFunction(){
mySingleFunction_1();
mySingleFunction_2();
mySingleFunction_3();
mySingleFunction_4();
}
Try to refactor your code. There is limit on the size of method in Java.
As mentioned in other answers there is a 64KB of bytecode limit for a method (at least in Sun's java compiler)
Too me it would make more sense to break that method up into more methods - each assigning certain related stuff to the array (might make more sense to use a ArrayList to do this)
for example:
public void addArrayItems()
{
addSculptureItems(list);
...
}
public void addSculptureItems(ArrayList list)
{
list.add("sculptures");
list.add("stonesculpture");
}
Alternatively you could load the items from a static resource if they are fixed like from a properties file
I have run into this problem myself. The solution that worked for me was to refactor and shrink the method to more manageable pieces. Like you, I am dealing with a nearly 10K line method. However, with the use of static variables as well as smaller modular functions, the problem was resolved.
Seems there would be a better workaround, but using Java 8, there is none...
I came to this question because I was trying to solve a similar problem. I wanted to hard code a graph that had 1600 elements into a 2D integer array for performance reasons. I was solving a problem on a leetcode style website and loading the graph data from a file was not an option. The entire graph exceeded the 64K maximum so I could not do a single static run of assignments. I split the assignments across several static methods each below the limit and then called each method one by one.
private static int[][] G = new int[1601][];
static {
assignFirst250();
assignSecond250();
assignSecond500();
assignThird500();
}
private static void assignFirst250() {
G[1] = new int[]{3,8,15,24,35,48,63,80,99,120,143,168,195,224,255,288,323,360,399,440,483,528,575,624,675,728,783,840,899,960,1023,1088,1155,1224,1295,1368,1443,1520,1599};
G[2] = new int[]{2,7,14,23,34,47,62,79,98,119,142,167,194,223,254,287,322,359,398,439,482,527,574,623,674,727,782,839,898,959,1022,1087,1154,1223,1294,1367,1442,1519,1598};
You can add another method to create space for your code for additional data space, you might have a method that is taking a large amount of data space. Try dividing your methods because I had the same issue and and fix it by creating another an additional method for the same data in my java Android code, The issue was gone after I did that.
I have an enum that causes the .java file to be over 500KB in size. Eclipse can build it for some reason; the eclipse-exported ant build.xml cannot. I'm looking into this and will update this post.
this is due to all code in single methods
solution :create more some small methods then this error will be gone
As there is a size limit for methods and you don't want to redesign your code as this moment, may be you can split the array into 4-5 parts and then put them into different methods. At the time of reading the array, call all the methods in a series. You may maintain a counter as well to know how many indexes you have parsed.
ok maybe this answer is too late but I think this way is better than another way so
for example, we have 1000 rows data in code
break them
private void rows500() {
//you shoud write 1-500 rows here
}
private void rows1000() {
you shoud write 500-1000 rows here
}
for better performance put an "if" in your codes
if (count < 500) {
rows500();
} else if (count > 500) {
rows1000();
}
I hope this code helps you
I need to include about 1 MByte of data in a Java application, for very fast and easy access in the rest of the source code. My main background is not Java, so my initial idea was to convert the data directly to Java source code, defining 1MByte of constant arrays, classes (instead of C++ struct) etc., something like this:
public final/immutable/const MyClass MyList[] = {
{ 23012, 22, "Hamburger"} ,
{ 28375, 123, "Kieler"}
};
However, it seems that Java does not support such constructs. Is this correct? If yes, what is the best solution to this problem?
NOTE: The data consists of 2 tables with each about 50000 records of data, which is to be searched in various ways. This may require some indexes later, with significant more records, maybe 1 million records, saved this way. I expect the application to start up very fast, without iterating through these records.
I personally wouldn't put it in source form.
Instead, include the data in some appropriate raw format in your jar file (I'm assuming you'll be packaging the application or library up) and use Class.getResourceAsStream or ClassLoader.getResourceAsStream to load it.
You may very well want a class to encapsulate loading, caching and providing this data - but I don't see much benefit from converting it into source code.
Due to limitations of the java bytecode files, class-files can not be larger than 64k iirc. (They are simply not intended for this type of data.)
I would load the data upon starting the program, using something like the following lines of code:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String... args) throws IOException {
List<DataRecord> records = new ArrayList<DataRecord>();
BufferedReader br = new BufferedReader(new FileReader("data.txt"));
String s;
while ((s = br.readLine()) != null) {
String[] arr = s.split(" ");
int i = Integer.parseInt(arr[0]);
int j = Integer.parseInt(arr[1]);
records.add(new DataRecord(i, j, arr[0]));
}
}
}
class DataRecord {
public final int i, j;
public final String s;
public DataRecord(int i, int j, String s) {
this.i = i;
this.j = j;
this.s = s;
}
}
(NB: The Scanner is quite slow, so don't be tempted to use it just because it has a simple interface. Stick with some form of BufferedReader and split, or StringTokenizer.)
Efficiency can of course be improved if you transform the data into a binary format. In that case, you can make use of the DataInputStream (but don't forget to go through some BufferedInputStream or BufferedReader)
Depending on how you wish to access the data, you might be better off storing the records in a hash-map (HashMap<Integer, DataRecord>) (having i or j as the key).
If you wish to load the data at the same time as the JVM loads the class file itself (roughly!) you could do the read / initialization, not within a method, but ecapsulated in static { ... }.
For a memory-mapped approach, have a look at the java.nio.channels-package in java. Especially the method
public abstract MappedByteBuffer map(FileChannel.MapMode mode, long position,long size) throws IOException
Complete code examples can be found here.
Dan Bornstein (the lead developer of DalvikVM) explains a solution to your problem in this talk (Look around 0:30:00). However I doubt the solution applies to as much data as a megabyte.
An idea is that you use enumerators, but I'm not sure if this suits to your implementation, and it also depends on how you are planning to use the data.
public enum Stuff {
HAMBURGER (23012, 22),
KIELER (28375, 123);
private int a;
private int b;
//private instantiation, does not need to be called explicitly.
private Stuff(int a, int b) {
this.a = a;
this.b = b;
}
public int getAvalue() {
return this.a;
}
public int getBvalue() {
return this.b;
}
}
These can then be accessed like:
Stuff someThing = Stuff.HAMBURGER;
int hamburgerA = Stuff.HAMBURGER.getA() // = 23012
Another idea is using a static initializer to set private fields of a class.
Putting the data into source could would actually not be the fastest solution, not by a long shot. Loading a Java class is quite complex and slow (at least on a platform that does bytecode verification, not sure about Android).
The fastest possible way to do this would be to define your own binary index format. You could then read that as a byte[] (possibly using memory mapping) or even a RandomAccessFile without interpreting it in any way until you start accessing it. The cost of this would be the complexity of the code that accesses it. With fixed-size records, a sorted list of records that's accessed via binary search would still be pretty simple, but anything else is going to get ugly.
Though before doing that, are you sure this isn't premature optimization? The easiest (and probably still quite fast) solution would be to jsut serialize a Map, List or array - have you tried this and determined that it is, in fact, too slow?
convert the data directly to Java source code, defining 1MByte of constant arrays, classes
Be aware that there are strict constraints on the size of classes and their structures [ref JVM Spec.
This is how you define it in Java, if I understood what you are after:
public final Object[][] myList = {
{ 23012, 22, "Hamburger"} ,
{ 28375, 123, "Kieler"}
};
It looks like you plan to write your own lightweight database.
If you can limit the length of the String to a realistic max size the following might work:
write each entry into a binary file, the entries have the same size, so you waste some bytes with each entry(int a, int b,int stringsize, string, padding)
To read an entry open the file as a random access file, multiply the index with the length of an entry to get the offset and seek the position.
Put the bytes into a bytebuffer and read the values, the String has to be converted with the String(byte[] ,int start, int length,Charset) ctor.
If you can't limit the length of a block dump the strings in an additional file and only store the offsets in your table. This requires an additional file access and makes modifiying the data hard.
Some informationa about random file-access in java can be found here http://java.sun.com/docs/books/tutorial/essential/io/rafs.html.
For faster access you can cache some of your read entries in a Hashmap and always remove the oldest from the map when reading a new one.
Pseudo code (wont compile):
class MyDataStore
{
FileChannel fc = null;
Map<Integer,Entry> mychace = new HashMap<Integer, Entry>();
int chaceSize = 50000;
ArrayList<Integer> queue = new ArrayList();
static final int entryLength = 100;//byte
void open(File f)throws Exception{fc = f.newByteChannel()}
void close()throws Exception{fc.close();fc = null;}
Entry getEntryAt(int index)
{
if(mychace.contains(index))return mychace.get(index);
long pos = index * entryLength; fc.seek(pos);ByteBuffer
b = new ByteBuffer(100);
fc.read(b);
Entry a = new Entry(b);
queue.add(index);
mychace.put(index,a);
if(queue.size()>chacesize)mychace.remove(queue.remove(0));
return a;
}
}
class Entry{
int a; int b; String s;
public Entry(Bytebuffer bb)
{
a = bb.getInt();
b = bb.getInt();
int size = bb.getInt();
byte[] bin = new byte[size];
bb.get(bin);
s = new String(bin);
}
}
Missing from the pseudocode:
writing, since you need it for constant data
total number of entries/sizeof file, only needs an additional integer at the beginning of the file and an additional 4 byte offset for each access operation.
You could also declare a static class (or a set of static classes) exposing the desidered values as methods. After all, you want your code to be able to find the value for a given name, and don't want the value to change.
So: location=MyLibOfConstants.returnHamburgerLocation().zipcode
And you can store this stuff in a hashtable with lazyinitialization, if you thing that calculating it on the fly would be a waste of time.
Isn't a cache what you need?
As classes it is loaded in the memory, not really limited to a defined size, should be as fast as using constants...
Actually it can even search data with some kind of indexes (exemple with the object hashcode...)
You can for exemple create all your data arrays (ex { 23012, 22, "Hamburger"}) and then create 3 hashmap:
map1.put(23012,hamburgerItem);
map2.put(22,hamburgerItem);
map3.put("Hamburger",hamburgerItem);
This way you can search very fast in one of the map according to the parameter you have...
(but this works only if your keys are unique in the map... this is just an exemple that could inspire you)
At work we have a very big webapp (80 weblogic instances) and it's almost what we do: caching everywhere. From a countrylist in database, create a cache...
There are many different kind of caches, you should check the link and choose what you need...
http://en.wikipedia.org/wiki/Cache_algorithms
Java serialization sounds like something that needs to be parsed... not good. Isn't there some kind of standard format for storing data in a stream, that can be read/looked up using a standard API without parsing it?
If you were to create the data in code, then it would all be loaded on first use. This is unlikely to be much more efficient than loading from a separate file - as well as parsing the data in the class file, the JVM has to verify and compile the bytecodes to create each object a million times, rather than just the once if you load it from a loop.
If you want random access and can't use a memory mapped file, then there is a RandomAccessFile which might work. You need either to load a index on start, or you need to make the entries a fixed length.
You might want to check whether the HDF5 libraries run on your platform; it may be overkill for such a simple and small dataset though.
I would recommend to use assets for storing such data.