Why does a Mattcher throw an exception after a successful find - java

I'm trying to write a loop that will find all the instances of "${arbitraryTextHere}" in an input string. E.g:
someText${findMe}moreText${findMeToo}EvenMoreText${DontForgetMe}
Here is my code:
Pattern placeholderPattern = Pattern.compile("\\$\\{[\\w|\\d]+\\}");
Matcher placeholderMatcher = placeholderPattern.matcher(templateString);
int workingIndex = 0;
while(placeholderMatcher.find()){
workingIndex = placeholderMatcher.start();
}
Note: The templateString I'm testing this out with is S"omeString ${someProp}"
The strange thing is that .find() has to return true in order to get inside the loop, but then .start() throws an IllegalStateException. The reason why this is so strange is that .start() only throws an IllegalStateException if the matcher's internal first variable is less than 0, but .find(), via the Matcher's boolean search(int from) method, will make sure that first is zero or greater unless no match is found, but if no match is found then .find() will return false, and we won't wind up in the loop body.
So what exactly is going on here?
Update: So I'f I encapsulate the above code so that it all runs in one unit test then it works. So I think the problem is related to having it in a class who's method is called from the unit test. But that's kind of weird. I'm going to dig into this aspect of the problem a bit more and then post an update.
Update: Ok, well I tried turning it off again and on again (I restarted my IntelliJ and recompiled my code) and now it's not broken anymore, so I think i must have screwed something up in that department.

As per the last update on my question, restarting IntelliJ and recompiling my code fixed things.

Related

Removing alphabetical characters from a string [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 months ago.
This post was edited and submitted for review 8 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I am new to java. Trying to create a function to remove a given string "arg" from myString which is previously set and return a new string not affecting myString. I believe i could solve this problem if it was not for all non alphabetical character of arg should remain in the string. so if arg has a 7 in it that should still be included in the final string. characters being removed are case insensitive as well.
I have edited the previous code and post, i can now run my code but I am not getting the correct results, I am trying to remove all numbers from arg before using it to remove all the characters. myString method is previously defined and working properly to return a string.
For examplecurrent string "my lucky numbers are 6, 8, and 19.", calling remove("ra6") would return "my lucky numbes e 6, 8, nd 19."
or "my lucky numbers are 6, 8, and 19.", calling remove("6,.") would return "my lucky numbers are 6, 8, and 19."
thank you!
public String remove(String arg) {
char[] charArray=arg.toCharArray();
String result="";
String newString="";
for (int i = 0; i < charArray.length; i++) {
if (!Character.isDigit(charArray[i])) {
result = result + charArray[i];
return result;}}
if (myString==null || myString=="") {
this.myString="";}
if (myString!=null) {
newString= myString.replaceAll(result,"");}
return newString;
}
Here is one way using streams. Just create a stream of characters via the chars() method and allow only letters to pass thru. Then each character to a String and join them together. Then remove that result from the original passed string.
String myString = "abcdTLK123efgh";
String arg = "TLK###123";
String result = remove(arg, myString);
System.out.println("Result = " + result);
prints
Result = abcd123efgh
The method
I modified the method to accept two strings.
the one to remove characters(arg).
and the from which to remove modified arg from myString
it works by
streaming all the characters of arg.
filtering out all but letters and digits
joining them as a string.
and then removing that filtered string from the myString.
public static String remove(String arg, String myString) {
if (myString == null || myString.isBlank()) {
return "";
}
return arg.chars().filter(
ch -> Character.isLetter(ch))
.mapToObj(Character::toString)
.collect(Collectors.collectingAndThen(
Collectors.joining(),
str -> myString.replace(str, "")));
}
Note: If myString is null then assigning an empty string to it will contain nothing to change. Nor an initial empty string. So I just returned an empty String if those conditions existed.
I believe i could solve this problem if it was not for all non alphabetical character of arg should remain in the string.
The good news is that you can solve it yourself.
The bad news is that the code above is in such a mess that it would be difficult for you to fix it by yourself. (Given your current level understand of Java syntax, way of working, etcetera.)
(Also, there is a long more wrong than the "if it were not for ..." ...)
So here is what I advise you to do.
Save a copy of the current version of the (entire) class somewhere safe so that you can look it again if you need to, or revert to it.
Develop a model of what the method needs to do and how it will do it; see below.
Delete all lines of code between the first { and last } shown in the question. Yes. Delete them.
Compose the new version of the code, one line at a time. As follows:
Add a line.
Compile the code (or let the IDE compile it for you).
Read the compilation error(s) that just appeared.
Understand the compilation errors.
Make the necessary changes to fix the compilation errors. Don't rely on your IDE's facility for suggesting corrections. (The IDE doesn't understand your code, what you are going to add next, or what you are trying to achieve. Its suggestions are liable to be unhelpful or even wrong.)
Repeat until you have dealt with all of the compilation errors that were introduced.
Now you are ready to add another line.
Once you have a complete method, you can then try to run it.
You will most likely find that the code doesn't work. But at least it will be valid Java code. And in the process of doing 4. above, you will (hopefully!) have learned enough Java syntax to be able to read and understand the code that you wrote. And 2. will help you understand what the code you are writing should do.
My other observation is that it looks like you have been adding and removing statements to this code with no clear understanding of what they do or what needs to happen. Maybe you started with some code that did something else ... correctly ... but it is hard to tell now.
Changing things randomly to try to make the code work is not a sensible approach. It rarely works. You need to have a model (or plan) in your head or on paper (e.g. as pseudo-code or flowcharts) about how the code ought to work.
Programming is about 1) developing the model, then 2) translating the model into code. The first part is the hard (and interesting) part. But if you skip the first part, the second part is an essentially random process, and unlikely to succeed.
The problem with starting with someone else's code is that you risk not developing a mental model of how that code works. Let alone the model that you are aiming for.
Finally, a professional programmer will use a version control system for their source code, and make relatively frequent commits of their code to their repository. Among other things, that allows them to quickly "roll back" to an earlier version if they need to, or keep track of exactly what they changed.
It is probably too early for you to learn about (say) using Git ... but it would help you solve your problem if you could just "roll back" all of the changes where you were "messing" with the code to get it to work.

Avoid JNI ERROR generated by Java code in Android

I'm developing a test for some hundreds of regex I have to manage in Android.
I encountered a catastrophic backtracking I cannot prevent, (i.e., the matcher enters an exponential complexity and it seems it is in an infinite loop, while, in reality, it is exploring a very huge number of possible matches), so I need to limit the overall execution of the matching using a timeout.
I've already found a possible approach here, but I also have to get the boolean return value from the find() method, so the Runnable is not the best choice.
Even the little variation proposed among the other answers in the link above, to avoid the use of thread is not applicable, because it is based upon an extension of CharSequence which simply doesn't work because charAt is not used in the matcher.find() (checked this twice, both with a breakpoint during debug and also reading the Matcher source). Edit: I found in a second time that also #NullPointerException already found that the charAt gets never called, but I don't know if since 3 years ago he found out a solution
So, the best option I found until now seems to be using a FutureTask, which has the possibility to specify a timeout and can also return a value. I implemented the following code:
private boolean interruptMatch(final Matcher matcher){
boolean res = false;
ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask<Boolean> future =
new FutureTask(new Callable() {
public Boolean call() {
return matcher.find();
}
});
executor.execute(future);
try {
res = future.get(2000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.d("TESTER","Find interrupted after 2000 ms");
} catch (ExecutionException e) {
Log.d("TESTER","Find ExecException after 2000 ms");
} catch (TimeoutException e) {
Log.d("TESTER","Find timeout after 2000 ms");
}
future.cancel(true);
executor.shutdownNow();
return res;
}
This part of code is being called by the main method, in an almost "classic" way:
pattern = Pattern.compile(pattern, java.util.regex.Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(inputString);
if (interruptMatch(matcher)) { // before the need to manage catastrophic backtracking here there was a simple if (matcher.find()){
// Do something
}
So, everythings seemed to work, at least for the first some hundreds patterns (also limiting in the timeout time the catastrophic backtracking long running find), until I got the following error:
JNI ERROR (app bug): weak global reference table overflow (max=51200)
It has been generated by the above java code (before this error didn't appear - cancelling the pattern which caused the catastrophic backtracking, obviously), but I cannot find out how to clean the global reference table, (I found a number of answers about similar issues generated directly by JNi code, but not from Java), not how to find a workaround or another valid approach.
EDIT: I further tried to debug and I found that the issue arises when I call the get method. I tried to follow the code of FutureTask, but I didn't find anything useful (and I get bored too fast).
Can you help me, please?
Thank you in advance
After other digging I found out that there is a tracked issue in Android, (it seems it deals with other topics, but it also answer mine) and from the replies I understand that it is just an issue which appear during debugging. I tested again my tester app and I found it's true: without debugging the above error doesn't happens. So, the severity of the issue is much lower and I can live with it (for me this is a closed issue) –

What can I change to make this code work properly?

I'm in the final stages of testing before I release the alpha version of a program I am writing. This may be a silly question but I just can't seem to figure it out. I understand what drjava is telling me, that I'm missing a variable, but I also don't understand because I never made a variable under the name "()". I'm not even sure you can set any type of variable to a open-close parenthesis. Anyways I was testing and while it works, it doesn't the way I want it to. I entered into the scanner "Mr. B." without the quotes of course. The program did not print the B. I'm thinking it might be the space in between Mr. and B, because other inputs with a space did the same. I can not release a version of my program knowing there is a GIANT glitch in the code. I'm wondering why, and I tried to fix it by changing ownersname.next(); to ownersname.nextLine and ownersname.next and ownersname.nextScanner and ownername.nextScanner. This is where the error comes in, when it says it can't find the variable until I change it back to it's original code, which is below.
Scanner ownersname = new Scanner(System.in);
String sownersname = ownersname.next();
System.out.println(sownersname + "? That is a nice name.");
I'm in the final stages of testing before I release the alpha version of a program I am writing.
You're creating a professional application? Please do tell us more about this.
I understand what drjava is telling me, that I'm missing a variable, but I also don't understand because I never made a variable under the name "()". I'm not even sure you can set any type of variable to a open-close parenthesis.
When posting questions here, if you have an error message from the compiler, please post the entire error message with your question. Don't paraphrase it. And indicate by obvious comment in your code, i.e., // ****** error here ***** where the error is occurring.
Anyways I was testing and while it works, it doesn't the way I want it to. I entered into the scanner "Mr. B." without the quotes of course. The program did not print the B. I'm thinking it might be the space in between Mr. and B, because other inputs with a space did the same.
Don't use Scanner#next() which gets only the next token -- the next word before reaching whitespace (here, Mr.), and will not get the rest of the text on the line. Instead use Scanner#nextLine() which gets you the whole line.
For example:
Scanner ownersname = new Scanner(System.in);
// String sownersname = ownersname.next(); // *** not this ***
String sownersname = ownersname.nextLine(); // *** but rather this ***
System.out.println(sownersname + "? That is a nice name.");
I can not release a version of my program knowing there is a GIANT glitch in the code.
Seriously, you're creating a professional application? I'm not yet at that stage, which is why I ask.
I'm wondering why, and I tried to fix it by changing ownersname.next(); to ownersname.nextLine and ownersname.next and ownersname.nextScanner and ownername.nextScanner. This is where the error comes in, when it says it can't find the variable until I change it back to it's original code, which is below.
I'd be curious to see your nextLine() method attempt, because that is the solution. Perhaps you were trying to call the method without using the method parenthesis.
I also assume that you're familiar with the Java API and have looked up the Scanner entry for it. If you did, you would see right away that there is no nextScanner() method for this class. This is one reason I have to wonder about your making a professional application at your stage. Again, I don't feel that I'm at the stage yet to create one yet, so please don't take this as an insult, just a curiosity.

Money Example from Kent Beck's TDD by example

So I have worked through the Money example in Kent Beck's book Test Driven Development by Example and have been able to get the code to work up until the last test that he writes:
#Test
public void testPlusSameCurrencyReturnsMoney(){
Expression sum = Money.dollar(1).plus(Money.dollar(1));
assertTrue(sum instanceof Money);
}
and here is the function that this calls
public Expression plus(Expression addend) {
return new Sum(this, addend);
}
When I run this, it gives java.lang.AssertionError, so my question is why is it giving this error and how do I fix it?
Lunivore already answered the question with how to solve the problem, but I think you should re-read the paragraph just before and after the block of code (and test), if you want to understand more on what Beck was trying to convey.
The last sentence reads "Here is the code we would have to modify to make it work:". That block of code was first entered on page 75 (with test case). Nothing was changed in end effect on page 79. It was just an indication of what we could change, if we wanted to keep this test.
"There is no obvious, clean way to check the currency of the argument if and only if it is Money. The experiment fails, we delete the test, and away we go".
He also stated that this test is ugly and concluded on the following page "Tried a brief experiment, then discarded it when it didn't work out".
I wrote this just in case you were thinking all of the examples just work and should be kept.
You're checking that the sum variable is a Money, but returning a Sum in the plus method.
So, unless Sum is a subclass of Money, that assertion will always fail.
To make it pass, you might want to do something like:
public Expression plus(Expression addend) {
return new Money(...<whatever>...);
}
Of course, Money would then have to be an Expression too.
Or you might want to evaluate the sum to get the money out of it. Or maybe even do sum instanceof Sum instead. It depends on what behavior you're actually trying to achieve.
By the way, beware the instanceof operator.

Findbugs and comparing

I recently started using the findbugs static analysis tool in a java build I was doing. The first report came back with loads of High Priority warnings. Being the obsessive type of person, I was ready to go knock them all out. However, I must be missing something. I get most of the warnings when comparing things. Such as the following code:
public void setSpacesPerLevel(int value)
{
if( value >= 0)
{
spacesPerLevel = value;
}
else
{
spacesPerLevel = 0;
}
}
produces a high priority warning at the if statement that reads.
File: Indenter.java, Line: 60, Type:
BIT_AND_ZZ, Priority: High, Category:
CORRECTNESS Check to see if ((...) &
0) == 0 in
sample.Indenter.setSpacesPerLevel(int)
I am comparing an int to an int, seems like a common thing. I get quite a few of that type of error with similar simple comparisons.
I have alot of other high priority warnings on what appears to be simple code blocks. Am I missing something here? I realize that static analysis can produce false positives, but the errors I am seeing seem too trivial of a case to be a false positive.
This one has me scratching my head as well.
for(int spaces = 0;spaces < spacesPerLevel;spaces++)
{
result = result.concat(" ");
}
Which gives the following findbugs warning:
File: Indenter.java, Line: 160, Type: IL_INFINITE_LOOP, Priority: High, Category: CORRECTNESS
There is an apparent infinite loop in sample.Indenter.indent()
This loop doesn't seem to have a way to terminate (other than by perhaps throwing an exception).
Any ideas?
So basically I have a handful of files and 50-60 high priority warnings similar to the ones above. I am using findbugs 1.3.9 and calling it from the findbugs ant task
UPDATE:
I have this build being executed by a hudson server and had the code being instrumented by Clover for code coverage. When I turned that off, all of my high priority warnings disappeared. That makes sense now. Thanks for the feedback.
UPDATE: I have this build being executed by a hudson server and had the code being instrumented by Clover for code coverage. When I turned that off, all of my high priority warnings disappeared. That makes sense now. Thanks for the feedback.
A side note:
for(int spaces = 0;spaces < spacesPerLevel;spaces++)
{
result = result.concat(" ");
}
If result is a java.lang.String, this may be inefficient, as you do the following steps for each space character:
create a new char[] to hold the result of the concatenation
create a new java.lang.String instance that is wrapped around the character array
If you do this repeatedly, especially when result is already long, this takes a lot of time.
If performance (both time and memory) is important for that method, you should consider using a StringBuilder (not thread-safe) or a StringBuffer (thread-safe).
Are you running Findbugs thru Eclipse plugin, ant or gui? is it possible that the code hasn't recompiled since you ran it (before making changes)?
if setSpacesPerLevel isn't too long, post the output of
javap -v TheClassThatContainssetSpacerPerLevel
As for the second bug, you'd have to show the whole loop before one could say if it was a problem.

Categories