java assert gives strange results - java

what should the following java code do?
public class foo{
public static void main(String[] args){
boolean mybool=false;
assert (mybool==true);
}
}
Should this throw an assertion error? and if not why not? (I'm not getting any errors!)

When running the program, you have to enable assertions in the Java VM by adding '-ea' to the command line:
java -ea -jar myprogram.jar

Java-language assertions are weird. You have to enable them when you launch the command line, and I don't like that.
For this reason, I tend to use 3rd-party libraries to do my assertions. Apache Commons Lang (via the Validator class), Spring (Via the Assert class) or even JUnit4 (via the Assert class) all provide this functionality, and it'll work regardless of VM settings. When you use Java5 static imports, they're just as easy to use as java assert, plus they're more flexible, plus they allow you to specify the error message in the exception.

This should be throwing AssertionErors.
You need to turn on assertions if you are using Eclipse. It has them disabled by default.
To do this, add -ea to the JVM arguments.

This makes the information if Assertions are enabled accessible in the program.
If assertions are disabled (this is the default) the assertion statement will not be executet, and mybool will have the value false.
if assertions are enabled (jvm argument -ea) the assertion will get executed, and by a side effect mybool will be set to true.
You can use that to enforce enabling or disabling of assertions. For example I have a Test in my TestSuites that failes if assertions are not enabled, in order to enforce that the assertions are always on when running the tests.

Related

DEBUG and RELEASE builds in Java (Eclipse)?

New to Java and Eclipse (but experienced with Visual Studio and Delphi). Using Eclipse Mars (4.5) and cannot find how to set the build configuration (DEBUG or RELEASE). Couple of related questions:
Are DEBUG/RELEASE supported in Java?
How do you switch between the two configurations?
Can you detect the configurations at build time and run conditional code like this (using Delphi as an example):
{$IFDEF DBG} CallDebugFunction(); {$ELSE} CallReleaseFunction(); {$ENDIF};
DEBUG/RELEASE are not exactly supported in java. But there are a few facts that are useful to remember, and a few other ways of accomplishing parts of the same thing.
The creators of java decided that there is great merit in having every single compilation unit producing the exact same bytecode regardless of external factors, so Java does not have a pre-processor.
The closest thing that java has to the kind of DEBUG/RELEASE that you are familiar with is the assert keyword. You can control whether assertions will be evaluated by supplying an -assertionsenabled (-ea for short) parameter to the VM. Read up on it, and also read up on how to pass parameters to the VM.
Note that VM parameters are runtime parameters, they have nothing to do with the compiler, which means that assertions will always be emitted by the compiler into the bytecode, and if you do not supply -ea, then the runtime will refrain from evaluating them. So, at the very least there will still always be a hidden if( assertionsEnabled ) { ... } statement to execute for every assertion.
Another thing worth remembering is that public static final variables are treated as compile-time constants, and the compiler may avoid emitting any bytecode for source code controlled by an if( false ) clause. However, the source code will always be compiled, so it has to be correct, despite the fact that no bytecode will be generated.
So, you can have a global variable defined as public static final boolean DEBUG = true to control all your debugging code, but you will have to manually change it in the source code and rebuild your project in order to produce a release build; java specifically refrains from providing any other way of accomplishing this.
Also, note that if( false ) (and by extension if( DEBUG )) will produce a warning about the condition being always true or always false, so I don't like using it.
The philosophy of java is that we generally do not care about performance to such a paranoid degree as to want to have total control over tiny little performance differences between DEBUG and RELEASE. Generally, the assert keyword is all that's needed, and actually (to my dismay) most java people do not even use assert due to various (lame, IMHO) reasons.
As for emitting debugging information, the vast majority of debugging info is generated anyway, because it has to be available at runtime through reflection. There is one tiny thing that I am aware of which you can control: the -parameters compiler option, but it is really insignificant, and it is possible that future versions of the compiler will deprecate the option and include the functionality that it controls as standard behavior.
This also means that java code can be reverse-engineered much more easily than C++ code, and for this reason there exist java obfuscators which pass the code through an identifier-mangling phase before sending it to the java compiler, so as to reduce the amount of useful information in the bytecode files.
You might be glad to know that this is all not too bad due to JITting: the bytecode gets compiled into machine code by the VM, and many optimizations are carried out at that stage, so you benefit from them always, not just on RELEASE.
As for detecting whether assertions are enabled, you can use the following code:
static boolean areAssertionsEnabled()
{
//noinspection UnusedAssignment
boolean b = false;
//noinspection ConstantConditions,AssertWithSideEffects
assert b = true;
//noinspection ConstantConditions
return b;
}
The noinspection thingies are for suppressing warnings in IntelliJ IDEA, a java IDE which is far superior to Eclipse. If you insist on using Eclipse you will have to find the equivalent warning suppression mechanisms for it.

Do JUnit Assertions ever get disabled?

Java assert statements are selectively enabled/disabled, based on config flags (eg, -ea). I read online that with JUnit assertions (eg, Assert.assertTrue), you don't need to worry about managing the assertion-config yourself. What exactly does this mean? Either:
1) JUnit assertions (mixed together with Prod code) are never disabled. They behave just like Validate statements, and always get run.
or
2) The JUnit test framework automatically enables all JUnit assertions when running JUnit tests. Whenever the application/code is run outside of JUnit, the JUnit assert methods do nothing at all.
or
3) JUnit assertions are always enabled/disabled by default, but there is a custom config/flag that can be used to disable/enable them
Which of the above is true?
--
Edit: Changed the wording a little bit to clear up any ambiguity.
This question seems to have opened up a can of worms with regards to coding-guidelines on when to use/not to use asserts. I'll post here the answer to my immediate question regarding whether JUnit Assert statements get disabled. Further down, you will find a discussion on the philosophical aspects of using assertions.
Summary: JUnit assert statements are never disabled, even when running in production with the disable-assertions flag.
Experiment: Created a small main function which throws an error in the very first line. The error was implemented in various different ways. I then ran the application from the command-line like so: mvn clean package; java $JAVA_OPTS -cp ....
Induced error by throwing IllegalArgument exception. Application failed with IllegalArgument exception.
Induced error by adding assert false and ran with assertions enabled (-ea). Application failed.
Induced error by adding assert false and ran with assertions disabled (-da). Application succeeded.
Induced error by adding Assert.assertTrue(false); and ran with assertions enabled (-ea). Application failed with AssertionError.
Induced error by adding Assert.assertTrue(false); and ran with assertions disabled (-da). Application failed with AssertionError.
Did a quick google search to see if there's any way to disable JUnit.Asserts. Didn't find anything. If anyone knows of a way to do so, please let me know, because I believe it's an important distinction.
Conclusion: assert keywords can be enabled/disabled using the -ea commandline flag. JUnit.Asserts cannot be enabled/disabled. If you want to add assertions to your production code, then this becomes a very important distinction. If you want the ability to disable them, use the assert keyword. If you want something that you know will always be enabled, then consider JUnit.Assert, or some other similar framework that throws AssertionErrors.
Regarding the philosophy behind assert usage:
It's good to add assertions of some form to your production code. See: https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage
Putting Assertions Into Your Code. There are many situations where it is good to use assertions, including:
Internal Invariants
Control-Flow Invariants
Preconditions, Postconditions, and Class Invariants
JUnit Asserts cannot be treated as a universal replacement for java assert keywords. The latter gives you the power to disable them, and the former doesn't. Hence, there is a design choice to be made in choosing which of the 2 to use.
Exceptions and Assertions serve very different purposes and should not be used interchangeably. The following discussion clarifies this further: When to use an assertion and when to use an exception
Related StackOverflow discussions:
assert vs. JUnit Assertions
I think you're confused between JUnit assertions and Java's built in assertions.
JUnit assertions are methods that throw an AssertionError exception and should only be used in your test code. JUnit code should not be used in production, only when running your JUnit tests during/between builds. The method names are named like assertEquals( expected, actual) and assertNull(Object) etc. You can't disable these assertions since they are method calls. Also your test code would be pretty useless if you could disable all the JUnit assert methodcalls.
Java's built in assertion is a boolean expression preceded by the assert keyword. If the expression returns false, then it too throws an AssertionError. This kind of assertion can be disabled in production to help speed up your code or turned on to help track down bugs. You can read more about the built in Java assert in the Java Programming Guide

Make Sonar override "don't declare 'throws Exception'" only in unit test classes

I agree that it's generally a bad idea to declare "throws Exception" in normal Java code.
However, I think it is a good idea to do this in unit tests. It simplifies the test method, but still results in any unexpected exceptions causing the test to fail.
I'd like to see if it's practical or possible to make Sonar only report this issue for classes not ending in "Test". I'd rather not add overrides in the code, I'd prefer to make this happen entirely in the Sonar configuration, or in the properties sent through sonar-runner.
Can anyone see a way to do this?
Since SonarQube 4.0 (or if you have an older version, using the Switch Off Violations plugin), you can define a pattern to ignore this rule on classes ending in Test:
Connect to SonarQube with a global administrator account
Go to: Administration > Configuration > General Settings > Analysis Scope
Find section: Issues > Ignore Issues on Multiple Criteria
Add an entry with:
Rule Key Pattern: squid:S00112
File Path Pattern: **/*Test.java
Please also note that recent versions of SonarJava (at least since 3.1) only apply a specific set of rules to test classes.

Popping debugger with code in Java

I used abort() In C to make my program crash. And debugger will trap this.
Maybe equivalent in Java should be exception. But Java also has very strict exception chaining policy, so using of exception for debugging purpose doesn't seem to be a good idea.
What should I use for this in Java? Intentional program crash for debugging purpose which can be trapped by debugger. (I am using Eclipse)
Update
It would be very nice if the code can be optionally opt-out on release build.
In Eclipse you can set debug points, and run in debug mode.
That said, there is a difference between a CheckedException (which must be caught by the calling function or passed up the chain) and an UncheckedException (which is closer to what you want). Throw the latter if you want to force a crash.
However, this is generally a bad way to program. You'll find better results using alternative means to catch the errors you want.
You can use assert(false). Assuming you're using Eclipse for the debugger, you can set Eclipse to break on specific exceptions (in this case, AssertionError). Make sure you enable assertions, otherwise it won't do anything.
Since you have to explicitly tell the JVM to enable assertions, I think this would count as "code [that] can be optionally opt-out on release build."
I do not know how to handle it in Eclipse. However, under JDB, this can be done by catching the Exceptions. Eclipse should have such an interface.
Using command line like this
"catch java.io.FileNotFoundException"
For details, please refer to here

java runtime tracing library to replace system.out.println

Have you heard of any library which would allow me to set up tracing for specific methods at runtime?
Instead of adding (and removing) lots of System.out.println in my code (and having to re-compile and re-deploy) I would like to have a magic thing which would print out a line for each call of selected method without any change in the code. This would work without re-compiling, so some kind of JVM agent (or some non-standard JVM would be needed?). Sounds like a job for aspect programming?
A typical scenario would be to start an application, configure the traced methods dynamically (in a separate file or similar) and then everytime a selected method is called a line with its name (and arguments) is printed out to System.out (or some log file).
Naturally one could think of tens of additional features, but this basic set would be a great tool. BTW, I use Eclipse interactive debugger too, not only the System.out tracing technique, but both have some advantages and sometimes Eclipse is not enough.
Yes what you are referring to is known as Aspect oriented programming. A typical library providing this for Java is AspectJ. You define what are called pointcuts, essentially regular expressions for classes and method names, including wildcards, and the code to execute at each pointcut, known as an advice. This is useful for logging and also security checks and similar cross cutting concerns.
You can turn pointcut advices on and off through configuration. You can have an advice execute before a method call, after it returns or even after it throws an exception. Arguments are also available.
An aspectj java agent is needed for this to work.
In my experience, that kind of very detailed tracing (much more detailed than one would normally use for logging) as a debugging technique is indicative of insufficient unit testing and integration testing.
You can do this using a tool called InTrace.
NOTE: InTrace is a free and open source tool which I have written.
Log4J useful for disabling logging depending on "log-level" (DEBUG, INFO, WARN, FATAL).
You specify in configuration file what the least level you want to appear in logs, e.g., don't log anything below INFO level, and voila!
Looks like there's yet another solution - called Byteman. In their own words:
Byteman is a tool which simplifies tracing and testing of Java
programs. Byteman allows you to insert extra Java code into your
application, either as it is loaded during JVM startup or even after
it has already started running. The injected code is allowed to access
any of your data and call any application methods, including where
they are private. You can inject code almost anywhere you want and
there is no need to prepare the original source code in advance nor do
you have to recompile, repackage or redeploy your application. In fact
you can remove injected code and reinstall different code while the
application continues to execute.
Jackplay is the tool you are looking for.
It allows you to enable logging on method entry and exit points without any coding or redeployment.
It also allows redefining a method body. It gives you web based UI as control panel to enable or undo tracing on your class.methods.

Categories

Resources