I have the following code:
if (maxLength>=0 && (++totalLength > maxLength))
throw new IllegalStateException("Form too large");
in a loop where bytes are read from byte array input stream. The maxLength is set to Integer.MAX_VALUE so I think that the condition could never be true (and I'm not talking about the size of the byte array in input stream which I'm absolutely sure is not long enough). But I get the IllegalStateException thrown from that line!!! Now the real bummer is that when I put a breakpoint on that throw line, everything is ok. How the hell is this possible?
EDIT:
both variables are of type int
totalLength is a local variable, maxLength is a parameter
the debugger don't stop there AND the exception is not thrown at all, when there is a breakpoint on that throw line.
I actualy don't know why I'm suspecting parallelism, it's just because it's web application
I admit that using MAX_VALUE is very risky (in the next step I will try to decrease this limit), but I would expect some other execption than that in the success branch of if statement. And moreover that byte array used in input stream is really not long enough. This should be plainly impossible situation in JVM:-).
The code above is in jetty-util-7.1.5.v20100705.jar in the class UrlEncoded and I'm using it by calling
byte[] decodedBytes;
byte[] encodedBytes;
// v pripade url encoded requestu je potreba pouze odriznout
// jmeno falesneho parametru nesouciho kodovany blok
encodedBytes = Arrays.copyOfRange(content, "encdata=".length(), content.length);
decodedBytes = decodeBytes(request, encodedBytes);
// priprav desifrovany text jako vstupni proud
decodedInputStream = new ByteArrayInputStream(decodedBytes);
// pokud je request url encoded je potreba jej manualne parsovat
// pro potreby funkci vracejicich parametry
UrlEncoded.decodeTo(decodedInputStream, parameters, request.getCharacterEncoding(), Integer.MAX_VALUE);
Are there any parallel issues with Integer.MAX_VALUE
No, this is most likely not due to any race-conditions (unless you have other threads modifying maxLength or so).
According to the JLS on integer is larger than Integer.MAX_VALUE so this is either due to a bug in your VM or based on the false assumption that maxLength is indeed Integer.MAX_VALUE.
The maxLength is set to Integer.MAX_VALUE so I think that the condition could never be true
Make sure totalLength is not a long.
(The snippet below always throws the exception.)
int maxLength = Integer.MAX_VALUE;
long totalLength = 2147483647;
if (maxLength>=0 && (++totalLength > maxLength))
throw new IllegalStateException("Form too large");
If it's not reproducible with the debugger, just give a more informative error message to the exception, for instance: "Form too large: " + totalLength + " is larger than " + maxLength
Are you sure you want to increment totalLength before the comparison, rather than after? If your totalLength going into that statement is equal to maxLength, the exception will be thrown... is that a possible scenario?
Try totalLength++ instead.
Just a thought. Hope this helps.
Now the real bummer is that when I put a breakpoint on that throw line, everything is ok
Do you mean the debugger doesn't stop there?
From your question title it seems you suspect a racing condition (multithreading) issue.
How are the variables defined?
Could you post some more code?
Could maxLength be modified elsewhere? Or is it final?
Related
I'm working on a Java CPU benchmark that tests the number of recursive calls for a method that returns the sum of all prime numbers, from a variable called start. This is how my method looks like:
private long recursive(long start, int size, int counter) {
long temp = findNextPrime(start);
if (temp > size) return 0;
try {
return temp + recursive(temp, size, counter + 1);
} catch (StackOverflowError e) {
System.out.println("Reached nr " + start + "/" + size + " after " + counter + " calls.");
return 0;
}
}
I am looking for a StackOverflowError exception and want to output the last sum calculated before reaching that exception. Everything seems to work fine from a logical point of view, when I'm using a smaller value for size. The prime numbers are picked up correctly, and the sum is calculated correctly.
The problem is for greater values of size, where the exception is actually thrown. When I don't output anything in the catch() section (I comment the System.out.println() line), everything seems to be okay, but when I just let the print line as it is, I receive the following error:
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class java.lang.invoke.StringConcatFactory
at java.base/java.lang.invoke.DirectMethodHandle.shouldBeInitialized(DirectMethodHandle.java:347)
at java.base/java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:193)
at java.base/java.lang.invoke.DirectMethodHandle.preparedLambdaForm(DirectMethodHandle.java:210)
at java.base/java.lang.invoke.DirectMethodHandle.make(DirectMethodHandle.java:105)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:2322)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:2278)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:2520)
at java.base/java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:2466)
at java.base/java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:592)
at benchmark.cpu.CPURecursionLoopUnrollingBenchmark.recursive(CPURecursionLoopUnrollingBenchmark.java:61)
at benchmark.cpu.CPURecursionLoopUnrollingBenchmark.recursive(CPURecursionLoopUnrollingBenchmark.java:59)
The last line repeats itself a huge number of times. Line 59 in my code represents the return statement from the try block (return temp + ...). I am using IntelliJ with a Java 11 SDK and never ever met this error before.
It is obviously a concatenation problem, because if I'm just outputting a simple string (without any + operators), everything seems to work fine. The string concatenation works outside this method.
I am not going to also display the other method (findNextPrime()), because I feel like wasting too much space and making the question more complex as it already is. If you need more details, please leave a comment and I will surely add the other method, too (or what you're asking for).
I have been working on a few projects lately that use a flood fill on a 2D array to create a grid map for a game.
Part of the flood fill algorithm I am using grabs the neighboring "cells" in the grid and floods them if they are an open space and ignores them if they are not.
However, because I am grabbing neighbor cells, I am grabbing items from the array relative to the current cell like this: grid[y][x-1].
Obviously, when x == 0 an out of bounds error is thrown. In order to address this I have been using a conditional statement to check that the index I am accessing is in the array. Like this:
if(x - 1 >= 0){do what I need to that neighbor}
I know I can also address the error by using a try catch.
However, I am not sure which is the proper solution.
There are a few specific questions I have:
1) Does using the conditional method to prevent an error from occurring, require more overhead and create less efficiency? (I may be flooding thousands of cells)
2) How exactly does the catch block work? Is it conditionally checking for errors in the background some how?
I also made a very small demo code to show you exactly what I am talking about, just scaled down:
public static void main(String[] args) {
//declare our test array and initialize size 3
String [] testArray = new String[3];
//This is here for one of the methods I have been trying to avoid errors on
int indexAdjuster = 5;
//this the index of the array we are adjusting
int i = 0;
//now throw an error! uncomment to confirm there is an error if you want
//testArray[i-indexAdjuster] = "error";
//testArray[i+indexAdjuster] = "error";
//IGNORE the error with a try catch
try{
//this would result in an out of bounds exception below index 0 (-5 specifically)
testArray[0-indexAdjuster] = "error";
//this would result in an out of bounds exception above index 2 (5 specifically)
testArray[0+indexAdjuster] = "error";
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("There was an error, but I ignored it");
}
//PREVENT an error with a condition test
//it first checks if the adjusted index is at least 0
//then it checks if the adjusted index is less than the length of the array
if(i - indexAdjuster >= 0 && i + indexAdjuster < testArray.length){
//this would result in an out of bounds exception below index 0 (-5 specifically)
testArray[0 - indexAdjuster] = "This would be an error, but it is prevented";
//this would result in an out of bounds exception above index 2 (5 specifically)
testArray[0 + indexAdjuster] = "This would be an error, but it is prevented";
}else{
System.out.println("We just prevented the error");
}
System.out.println("Test Complete");
}
It depends, specifically on what you primary focus is: Speed or clean code.
If the error condition occurs rarely and the check is costly, catching an exception may be cheaper than checking beforehand. This conflicts the commonly accepted rule that catch blocks should not be used for regular flow control. Exceptions should be used to catch unexpected error conditions, an index outside an array is hardly unexpected.
The test can also be extracted into a separate method, making the code easier to read:
static boolean isValidIndex(String[] array, int i) {
return i >= 0 && i < array.length;
}
Or use a resilient access method:
static String getIndex(String[] array, int i) {
return i >= 0 && i < array.length ? array[i] : null;
}
(You may want to replace null with a constant value indicating an invalid value).
In your code you can simply use the getIndex() method for whatever index you calculated and act on the value it returns instead of the index. Same can be done for assigning to an index, if its appropiate to just ignore attempted assignments to non-existing indices:
static void setIndex(String[] array, int i, String value) {
if (i >= 0 && i < array.length)
array[i] = value;
}
The main issue you face is deciding if an out-of-bounds condition is just a normal case that has a reasonable default handling option or if it represents a real error that warrants aborting the method or program.
If its a real error condition, don't prevent it, don't catch it. Let it throw and bubble up the call stack. Whatever caller level initiated the whole action should be the one that responds to the execption. Its important to decide sensibly who is responsible for the handling, a deep-down detail method has often not enough information to make a reasonable decision what an error means - in those cases assign the responsibility to the caller (repeat until the caller can make the decision).
Using if statement to check your boundaries cause lots of overhead in each loop iteration.
I suggest you allocate a bigger array by 1 like:
String [] testArray = new String[3+1];
This cause that you don't need any if condition.
In response to your question about exception handling, it does not run any condition in background. It runs your code and after causing access violation determines you catch clauses.
im solving some questions in java and i come across this line in the question... " The total size of the input doesn't exceed 300 KB" , " The total size of the input doesn't exceed 256 KB"
my doubt is how can i make sure that my input is less than that value.
i actually tried using
CountingInputStream (CountingInputStream input = new CountingInputStream(System.in);)
to validate it. this is an external jar file by Google.
but when i submit my solution in the online compilers, CountingInputStream is not taken by the compiler. so how do i do it without using this ?.. in a general way ?
CountingInputStream input = new CountingInputStream(System.in);
System.out.println("Enter Values: ");
while (scanner.hasNext() && input.getCount() < (256 * 1024))
this is now im doing ...but is there a way where i can control my input without using CountingInputStream. Kindly help
Write your own class that decorates an InputStream, overriding the read method to count bytes and then throw an exception when the number of bytes exceeds some threshold. Your driver could look like this:
InputStream in = new ByteLimiterInputStream(new FileInputStream("file.bin"));
while(...)
in.read();
This will throw an exception when you've read too much data. It's up to you to write the ByteLimiterInputStream class. This is an academic exercise after all: exercise your own brain and don't ask others for the answers.
Use an InputStream, call the read() method, and increment a counter.
read() will return a single byte, or -1 at end of stream.
e.g.
int MAX = 256 * 1024;
int count = 0;
while (true) {
int return = is.read();
if (return == -1) break;
if (++count >= MAX) {
// maximum limit reached
} else {
// store the byte somewhere, do something with it...
}
}
---EDIT below
I'm actually implementing the Mina ProtocolCodecFilter in order to receive messages from a serial device.
The codec specifies multiple different messages (with their pojos), and even thou the implementation works correctly 99% of the time, I'm getting issues with one type of message: the only message that doesn't have a fixed length. I can know the minimum length, but never the maximum.
This is the exception message I'm receiving (just the important parts):
org.apache.mina.filter.codec.ProtocolDecoderException: org.apache.mina.core.buffer.BufferDataException: dataLength: -2143812863 (Hexdump: 02 01 A2 02 01 A0 02)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:25
...
Caused by: org.apache.mina.core.buffer.BufferDataException: dataLength: -2143812863
at org.apache.mina.core.buffer.AbstractIoBuffer.prefixedDataAvailable(AbstractIoBuffer.java:2058)
at my.codec.in.folder.codec.MAFrameDecoder.doDecode(MAFrameDecoder.java:29)
at org.apache.mina.filter.codec.CumulativeProtocolDecoder.decode(CumulativeProtocolDecoder.java:178)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:241)
Sometimes the dataLength is negative, sometimes positive (didn't find any clue about the cause of this).
The MAFrameDecoder:29 is the second sentence of my implementation of the CumulativeProtocolDecoder's doDecode() method (MAX_SIZE=4096):
public boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception
{
boolean result=false;
if(in.prefixedDataAvailable(4, MAX_SIZE)) //-->This is line 29
{
int length = in.getInt();
byte[] idAndData = new byte[length];
in.get(idAndData);
//do things, read from buffer, create message, out.write, etc
//if all has been correct, result=true
}
return result;
}
While debugging the error through a TCP sniffer, we figured out that the exception was thrown when multiple messages where inserted in the same IoBuffer (in).
Seems like my Decoder simply cannot handle multiple messages inside the same buffer. But as I told before, there's also the non-fixed length message issue ( which I really can't know if it has some relevance ). In other doDecode implementations I've seen another methods to manage the buffer, such as:
while (in.hasRemaining())
or
InputStream is=in.asInputStream();
Anyway, I'm trying to avoid blind steps, so this is why I'm asking this here. Instead of just fixing the error, I would like to know the reason of it.
Hope you can help me, any advice would be really appreciated. : )
p.s: The encoder that sends me the messages through the buffer has its autoExpand parameter in false.
EDIT 10/11/2014
I've been exploring the AbstractIoBuffer method and found out this:
#Override
public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
if (remaining() < prefixLength) {
return false;
}
int dataLength;
switch (prefixLength) {
case 1:
dataLength = getUnsigned(position());
break;
case 2:
dataLength = getUnsignedShort(position());
break;
case 4:
dataLength = getInt(position());
break;
default:
throw new IllegalArgumentException("prefixLength: " + prefixLength);
}
if (dataLength < 0 || dataLength > maxDataLength) {
throw new BufferDataException("dataLength: " + dataLength);
}
return remaining() - prefixLength >= dataLength;
}
The prefixLength I'm sending is 4, so the switch enters on the last valid case:
dataLength = getInt(position());
After that, it throws the BufferDataException with the negative dataLength, which means the AbstractIoBuffer's position() method is returning a negative value.
I always thought that a nioBuffer could never hold a negative value on its position parameter. Any clues of why is this happening?
I think you should try first reading the size of the packet you have to decode, and ensuring you have enough bytes remaining in the buffer for the decoding to complete successfully.
If there aren't enough bytes you should return false, so the cumulative protocol decoder can get more data for you.
Be careful to return the buffer to the appropriate position before returning the buffer, otherwise you will lose the length data for the next iteration. (If you are using 4 bytes for the length you should be rewinding 4 bytes).
Edit: You could actually use the mark() and reset() methods of the IoBuffer to achieve this behaviour
Whenever I try to execute this it gives me FC on my application
int a, b;
Random s = new Random();
if (diffi.contains("easy") && name.contains("sub")) {
a = s.nextInt(21);
b = s.nextInt(a);
}
But when remove "a " and put a number in its place then it starts working
int a, b;
Random s = new Random();
if (diffi.contains("easy") && name.contains("sub")) {
a = s.nextInt(21);
b = s.nextInt(21);
}
I want the second number "b" to be smaller than a in all cases
You'll get an exception if the first call to nextInt returns 0. Then the second call can't return a value which is greater than or equal to 0 but less than 0, hence the exception.
From the docs for Random.nextInt:
Throws: IllegalArgumentException - if n is not positive
You should step back for a moment though, and work out why your diagnostic approach didn't actually see those exception details. Did you check the application logs? I'd expect the exception to be clear, with the right exception, which would then make it fairly obvious what was wrong.
EDIT: I very much doubt that it's actually throwing an exception whenever that code is executed. Instead, I suspect that either that code is executing many times (so eventually you'll see that a is 0 and the exception will be thrown) or you've just been unlucky.