Unpredictable Java Behavior

I am pulling my hair out with this and I thought I'd see if more experience from other Java people could shed light on the problem. There is a large amount of program code that I wrote, which in itself is part of a larger project, so I can’t just publish it. However, I will focus on the problem ...

Problem: My code does not return the expected simulation results. Each time a simulation is performed, various statistics are recorded. Despite the fact that the code is identical (!), The results obtained differ from each other.

I am sure this is not a problem (although if you think there is a "gotcha", please shout):

  • A random number generator is used, but each time it is set with the same value.
  • The program is single-threaded, so race conditions should not be a problem.
  • The behavior occurs both in debug mode, in stand-alone jar, and in normal execution from the IDE (I use eclipse).
  • Static elements are used between objects in lists. Used for each design, but it must be done in the same order every time.
  • When sorting the lists just mentioned, Collections.sort () is used and therefore must be stable (again, the lists should be ordered in the same order)

Can anyone think of something that I might forget here? It seems incomprehensible at the moment! Thanks!

+4
source share
6 answers

Are you sure you are using the instance of Random that you created in all places? Remember that calls to Math.random () use their own instance of Random.

+3
source

I assume that you have redefined both equals() and hashCode() in your objects (or you created a custom comparator). If your random number is used in your objects, this is not a criterion in sorting, right?

Also, if you sort these items and then put them in a HashMap or HashSet - these structures will not save your order - use TreeSet or TreeMap instead.

+3
source

try adding a lot of tracing to the application, and then look at the logs to see where they diverge.

+2
source

You can track the execution of your Java code with the InTrace tool. This will allow you to compare the detailed control flow between different program runs.

NOTE. InTrace is the free open source tool I wrote.

+1
source

Is there any chance of garbage collection? This may add a bit of randomness to your time. If you use the Sun JVM, there are some options for printing GC information:

  -XX: -PrintGC Print messages at garbage collection.  Manageable.
     -XX: -PrintGCDetails Print more details at garbage collection.  Manageable.            
                                (Introduced in 1.4.0.)
     -XX: -PrintGCTimeStamps Print timestamps at garbage collection.  Manageable
                                (Introduced in 1.4.0.)

Details are taken from this page .

You can also look at jstat to get performance statistics on what is going on.

0
source

It's hard to say without knowing your code, but here are some points when I start looking.

Make sure all your individual classes are working properly. This means that you should unit test at least your main classes.

Insert assert-Statement into all private methods for additional verification to make sure that the data you pass to your helper methods is valid. (DO NOT use assert with public methods, use Exceptions).

Add logging (DEBUG level if you use log4j or the like) or simple System.out.println () instructions at all critical points to get an idea where the values ​​are changing. This will help you understand how your data flows through your code.

Since you are using eclipse, use a debugger and go through your code and watch for unexpected data changes.

Check out false assumptions. This, for example, is the business logic in the else block for conditions that are not pure true / false checks. For example, you often find such code in the GUI

 if (button == OK_BUTTON) { doOkButton(); } else { doCancelBotton(); // VERY dangerous. could be any Button } 

Fix it before

 if (button == OK_BUTTON) { doOkButton(); } else if (button == CANCEL_BUTTON) { doCancelBotton(); } else { assert false : "Oops, a new button?" } 

You said you were using a random number generator. Are you sure that you use the correct one every time, and this does not add randomness to your result? What exactly are you using it for?

Do you use any time? For example, System.currentTimeMillies?

Are you sure you are using the right collection? Not everyone is sorted and ordered and may give different results each time the application starts, if you try to view all the elements.

Make sure all classes you use in collections have the correct equals () AND hashCode () values

Do you use autoboxing? Be careful when comparing

  new Integer(5) == new Integer(5) 

is false because you are comparing two object references and not values ​​either,

 Integer i = new Integer(5); i++; 

creates a new object in i ++. This can be difficult to detect, and most of the time, if you work with primitives and collections, autoboxing occurs.

Do you use any third-party library that could invalidate your assumptions (race conditions, etc.).

Use a tool like FindBugs to statically analyze your code. This may give you some advice.

What would I start. Good luck

0
source

Source: https://habr.com/ru/post/1302896/


All Articles