175

We know it can in JavaScript.

But is it possible to print "Success" message on the condition given below in Java?

if (a==1 && a==2 && a==3) {
    System.out.println("Success");
}

Someone suggested:

int _a = 1;
int a  = 2;
int a_ = 3;
if (_a == 1 && a == 2 && a_ == 3) {
    System.out.println("Success");
}

But by doing this we are changing the actual variable. Is there any other way?

Maroun
  • 94,125
  • 30
  • 188
  • 241
Taylor Sen
  • 1,513
  • 2
  • 8
  • 7
  • 5
    `&&` is logical `and` operator, which means that `a` should be having value 1, 2 and 3 at the same time which is logically impossible. The answer is NO, not possible. Do you want to write an `if` statement that checks if `a` has one of the values 1, 2 OR 3? – Boris Pavlović Jan 22 '18 at 14:14
  • 3
    Any variable can never hold two different values at the same time. So the expression `a==1 && a==2` will _always_ evaluate to `false`. – Seelenvirtuose Jan 22 '18 at 14:15
  • 1
    i knew it that's why i am asking – Taylor Sen Jan 22 '18 at 14:17
  • 16
    Note to everyone: This question might come from the same question for Javascript: https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true , in which case the answer is `yes` – nos Jan 22 '18 at 14:18
  • use int[] array. – AA Shakil Jan 22 '18 at 14:18
  • 30
    @ArthurAttout Not a duplicate, that question is for Javascript, not Java. – nos Jan 22 '18 at 14:19
  • 1
    @nos The answer is still valid – Arthur Attout Jan 22 '18 at 14:21
  • 13
    The one using [whitespace in variable names](https://stackoverflow.com/a/48274520/1639625) works in Java, too. But of course this is basically the same as using `_`, except you can't see it. – tobias_k Jan 22 '18 at 14:26
  • For two cases one could take `a` and Cyrillic a; `а`. – Joop Eggen Jan 22 '18 at 14:26
  • 8
    @Seelenvirtuose True, but `if(a==1 && a==2 && a==3)` is not necessarily evaluated at the same time. And that can be used to make this work without having to resort to Unicode tricks. – Erwin Bolwidt Jan 22 '18 at 15:11
  • 4
    Reminds me of [Write a program that makes 2 + 2 = 5](https://codegolf.stackexchange.com/a/28818/76090) – phflack Jan 22 '18 at 15:54
  • 1
    @ThomasWeller: Yes, it is (as it is for almost any language), see https://stackoverflow.com/a/48301772/40347. We don't need this as a separate question for all languages as the underlying issues are the same. – Dirk Vollmar Jan 22 '18 at 20:04
  • @phflack: What's funny with this golf answer and its 670 upvotes is that `2 + 2 == 5` is still `False`. – Eric Duminil Jan 22 '18 at 21:27
  • 1
    Is there anything like Perl 6's [Junctions](https://docs.perl6.org/type/Junction) in Java? In Perl 6 you can write `$a = any(1,2,3);` and then `$a` will simultaneously represent all three values, making this true: `$a == 1 && $a==2 && $a==3`. – Christopher Bottoms Jan 23 '18 at 19:40
  • 1
    I've posted a PHP spin-off of this question [here](https://stackoverflow.com/questions/48336506/can-a-1-a-2-a-3-ever-evaluate-to-true). It seems incredibly simple to do `$a == 1 && $a == 2 && $a == 3`. – Blue Jan 23 '18 at 19:55
  • 2
    A big difference compared to the javascript version is how javascript is singlethreaded and to achieve the success you more or less have to deliberately break things. In Java as a multi-threaded environment the possibility of a success in a scenario like this is something you must be acutely aware of and deliberately design against, or else things will break. – DHa Jan 24 '18 at 16:20
  • Everyone saying it's impossible is wrong; see the top answer. @OP: Please read the top answer; it answers your question very well, and I'd recommend accepting it. – Nic Jan 25 '18 at 04:19
  • For a moment I thought this was the previous JS question when I saw it on the HNQ list. It left me wondering where all the other 20+ answers were haha – catastrophic-failure Jan 25 '18 at 12:55
  • 3
    I'm voting to close this question as off-topic because it's utterly pointless – Dancrumb Jan 28 '18 at 03:34
  • [Standard loopholes closed](https://codegolf.meta.stackexchange.com/a/1657/45632). – MC Emperor Feb 26 '19 at 12:32

8 Answers8

328

Yes, it's quite easy to achieve this with multiple threads, if you declare variable a as volatile.

One thread constantly changes variable a from 1 to 3, and another thread constantly tests that a == 1 && a == 2 && a == 3. It happens often enough to have a continuous stream of "Success" printed on the console.

(Note if you add an else {System.out.println("Failure");} clause, you'll see that the test fails far more often than it succeeds.)

In practice, it also works without declaring a as volatile, but only 21 times on my MacBook. Without volatile, the compiler or HotSpot is allowed to cache a or replace the if statement with if (false). Most likely, HotSpot kicks in after a while and compiles it to assembly instructions that do cache the value of a. With volatile, it keeps printing "Success" forever.

public class VolatileRace {
    private volatile int a;

    public void start() {
        new Thread(this::test).start();
        new Thread(this::change).start();
    }

    public void test() {
        while (true) {
            if (a == 1 && a == 2 && a == 3) {
                System.out.println("Success");
            }
        }
    }

    public void change() {
        while (true) {
            for (int i = 1; i < 4; i++) {
                a = i;
            }
        }
    }

    public static void main(String[] args) {
        new VolatileRace().start();
    }
}
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • 84
    This is a brilliant example! I think I'll steal it next time I'm discussing potentially dangerous concurrency issues with a junior dev :) – Alex Pruss Jan 22 '18 at 15:13
  • 6
    It’s not very likely without `volatile`, but in principle, this can even happen without the `volatile` keyword and it could happen an arbitrary number of times, while, on the hand, there is no guaranty that it will ever happen, even with `volatile`. But of course, having it happening in practice, is quiet impressive… – Holger Jan 22 '18 at 18:11
  • 5
    @AlexPruss I just did on all devs, not just juniors in my company ( I *knew* it could be possible ), 87% success of failures in answers – Eugene Jan 22 '18 at 20:17
  • 3
    @Holger True, no guarantees of either. On a typical multiple-full-core or multi-cpu architecture, where both threads get assigned to a separate core, it's quite likely though that it will happen with `volatile`. The memory barriers created to implement `volatile` slow the threads down and make it more likely that they operate in-sync for short periods of time. It happens far more often than I expected. It's very timing-sensitive, but I see roughly that between 0.2% and 0.8% of the evaluations of `(a == 1 && a == 2 && a == 3)` return `true`. – Erwin Bolwidt Jan 23 '18 at 01:36
  • How come anonymous classes can still access variable `a` when `a` is not final nor effectively final? Correct me if I'm wrong, your code seems to contradict java 8 docs. – dkonayuki Feb 27 '18 at 05:56
  • 1
    @dkonayuki `a` is a field, not a local variable. The 'final' and 'effectively final' rules only apply to local variables. – Erwin Bolwidt Feb 27 '18 at 06:46
88

Using concepts (and code) from a brilliant code golf answer, Integer values can be messed with.

In this case, it can make ints casted to Integers be equal when they wouldn't normally be:

import java.lang.reflect.Field;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        Class cache = Integer.class.getDeclaredClasses()[0];
        Field c = cache.getDeclaredField("cache");
        c.setAccessible(true);
        Integer[] array = (Integer[]) c.get(cache);
        // array[129] is 1
        array[130] = array[129]; // Set 2 to be 1
        array[131] = array[129]; // Set 3 to be 1

        Integer a = 1;
        if(a == (Integer)1 && a == (Integer)2 && a == (Integer)3)
            System.out.println("Success");
    }
}

Unfortunately it's not quite as elegant as Erwin Bolwidt's multithreaded answer (as this one requires Integer casting), but still some fun shenanigans take place.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
phflack
  • 2,729
  • 1
  • 9
  • 21
  • Very interesting. I was toying with abusing `Integer`. It's a shame about the casting but it's still cool. – Michael Jan 22 '18 at 16:10
  • @Michael I can't quite figure out how to get rid of the casting. `a` being set to 1/2/3 will satisfy `a == 1`, but it doesn't go the other way – phflack Jan 22 '18 at 16:11
  • 4
    I answered this question a few days ago in JS/Ruby/Python and [`Java`](https://stackoverflow.com/a/48298565/6419007). The least ugly version I could find was to use `a.equals(1) && a.equals(2) && a.equals(3)`, which forces `1`, `2` and `3` to be autoboxed as `Integer`s. – Eric Duminil Jan 22 '18 at 21:23
  • @EricDuminil That might take some of the fun out, because what if you made `a` be a class with `boolean equals(int i){return true;}`? – phflack Jan 22 '18 at 21:25
  • 1
    As I said, it's the least ugly but it's still not optimal. With `Integer a = 1;` on the line before, it's still clear `a` really is an Integer. – Eric Duminil Jan 22 '18 at 21:26
  • To my understanding `cache` is an implementation optimization detail in the Hotspot JVM, and will probably not work on other JVM's. – Thorbjørn Ravn Andersen Aug 27 '20 at 19:51
52

In this question @aioobe suggests (and advise against) the use of C preprocessor for Java classes.

Although it is extremely cheaty, that's my solution:

#define a evil++

public class Main {
    public static void main(String[] args) {
        int evil = 1;
        if (a==1 && a==2 && a==3)
            System.out.println("Success");
    }
}

If executed using the following commands it will output exactly one Success:

cpp -P src/Main.java Main.java && javac Main.java && java Main
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pado
  • 1,497
  • 16
  • 28
  • 6
    This kind of feels like running code through a find and replace before actually compiling it, but I could definitely see somebody doing something like that as part of their workflow – phflack Jan 24 '18 at 13:53
  • 1
    @phflack I like it, arguably this question is about showing the dangers of making assumptions when reading code. It's easy to assume `a` is a variable, but it can be any arbitrary piece of code in languages with a preprocessor. – kevin Jan 25 '18 at 07:04
  • 2
    It's not Java. It's the language "Java after passed over C preprocessor". Similar loophole used by [this](https://codegolf.stackexchange.com/a/34992/69850) answer. (note: [tag:underhanded] is **off-topic** for Code Golf now) – user202729 Jan 28 '18 at 05:02
  • 1
    I believe this is the exact reason why Java doesn't have a pre-processor. – Thorbjørn Ravn Andersen Aug 27 '20 at 19:52
40

As we already know that it is possible to make this code evaluate to true thanks to great answers of Erwin Bolwidt and phflack, I wanted to show that you need to keep a high level of attention when dealing with a condition that looks like the one presented in the question, as sometimes what you see might not be exactly what you think it is.

This is my attempt to show that this code prints Success! to the console. I know I cheated a bit, but I still think this is a good place to present it right here.

No matter what the purposes of writing code like this are - better to know how to deal with the following situation and how to check if you're not wrong with what you think you see.

I used the Cyrillic 'a' which is a distinct character from the latin 'a'. You can inspect the characters used in the if statement here.

This works because the names of the variables are taken from different alphabets. They are distinct identifiers, creating two distinct variables with a different value in each.

Note that if you want this code to work properly, character encoding needs to be changed to one supporting both characters, e.g. all Unicode encodings (UTF-8, UTF-16 (in BE or LE), UTF-32, even UTF-7), or Windows-1251, ISO 8859-5, KOI8-R (thank you - Thomas Weller and Paŭlo Ebermann - for pointing it out):

public class A {
    public static void main(String[] args) {
        int а = 0;
        int a = 1;
        if(а == 0 && a == 1) {
            System.out.println("Success!");
        }
    }
}

(I hope you will never have to deal with that sort of problem any time in the future.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Przemysław Moskal
  • 3,551
  • 2
  • 12
  • 21
  • @Michael What do you mean it doesn't show up well? I've written it on the mobile phone and here it looks ok to me, even when switching to desktop view. If it would make my answer better please feel free to edit it tuo make it clear as I find it a bit hard now. – Przemysław Moskal Jan 22 '18 at 16:00
  • @Michael Thank you very much. I thought that what I admitted at the end of my answer is enough :) – Przemysław Moskal Jan 22 '18 at 16:09
  • @mohsenmadi Yeah, I can't check it here on mobile phone, but I'm pretty sure that before edit, last sentence was about using different languages in my example :P – Przemysław Moskal Jan 22 '18 at 16:15
  • Why should █==0 be any similar to a==1? – Thomas Weller Jan 22 '18 at 19:41
  • @ThomasWeller If I include information about changing encoding to UTF-8 will it cover your expectations? – Przemysław Moskal Jan 22 '18 at 19:45
  • @ThomasWeller I edited my answer anyway to make it more clear. Thank you for pointing it out. – Przemysław Moskal Jan 22 '18 at 19:56
  • 1
    More nitpicking: You don't necessarily need UTF-8 (though that is recommended anyways), any character encoding which has both `а` and `a` works, as long as you tell your editor what encoding it is in (and possibly the compiler, too). All Unicode encodings work (UTF-8, UTF-16 (in BE or LE), UTF-32, even UTF-7), as well as e.g. Windows-1251, ISO 8859-5, KOI8-R. – Paŭlo Ebermann Jan 23 '18 at 22:33
  • I've already encountered that problem. A CAS of mine (Derive 6), has the synonym mu for µ (i.e., if I type in mu and let it simplify the expression, mu turns into a µ). However, somebody messed up, and the simplified mu and the Alt GR µ are different letters... – Sudix Jan 25 '18 at 11:48
  • @Sudix yes, there are two different characters, `U+03BC` (`μ`, GREEK SMALL LETTER MU) and `U+00B5` (`µ`, MICRO SIGN, legacy from iso-latin-1). There are lots of characters about which Unicode considers that they *should* be the same single character, but exist as distinct characters merely for compatibility with (lossless conversions from and to) legacy character sets. – Holger Jan 25 '18 at 13:43
29

There is another way to approach this (in additional to the volatile data-racing approach that I posted earlier), using the power of PowerMock. PowerMock allows methods to be replaced with other implementations. When that is combined with auto-unboxing, the original expression (a == 1 && a == 2 && a == 3), without modification, can be made true.

@phflack's answer relies on modifying the auto-boxing process in Java that uses the Integer.valueOf(...) call. The below approach relies on modifying auto-unboxing by changed the Integer.intValue() call.

The advantage of the below approach is that the original if-statement given by the OP in the question is used unchanged, which I think is the most elegant.

import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.replace;

import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@PrepareForTest(Integer.class)
@RunWith(PowerMockRunner.class)
public class Ais123 {
    @Before
    public void before() {
        // "value" is just a place to store an incrementing integer
        AtomicInteger value = new AtomicInteger(1);
        replace(method(Integer.class, "intValue"))
            .with((proxy, method, args) -> value.getAndIncrement());
    }

    @Test
    public void test() {
        Integer a = 1;

        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        } else {
            Assert.fail("(a == 1 && a == 2 && a == 3) != true, a = " + a.intValue());
        }
    }

}
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • Can Powermock replace synthetic methods like the `access$nnn` methods used to read `private` fields of inner/outer classes? That would allow some other interesting variants (which even work with an `int` variable)… – Holger Jan 23 '18 at 14:21
  • @Holger Interesting idea, I see what you mean. It's not working yet - not clear what's stopping it from working. – Erwin Bolwidt Jan 23 '18 at 14:31
  • Really nice, that's what I was trying to do, but I found that changing static method from immutable class would be quite difficult without manipulating the bytecode. Seems I was wrong, never heard of PowerMock though, I wonder how it does that. As a side note, phflack's answer doesn't relies on autoboxing: he changes the adresses of the cached Integer (so the == are actually comparing Integer object adresses rather than values). – Asoub Jan 23 '18 at 17:28
  • 2
    @Asoub the casting (`(Integer)2`) boxes the int. [Looking more into reflection](https://stackoverflow.com/a/15966918/5475891), it looks like it isn't possible to do this with unboxing using reflection, but may be possible with [Instrumentation](https://stackoverflow.com/a/15967008/5475891) instead _(or with PowerMock, as in this answer)_ – phflack Jan 23 '18 at 20:43
  • @Holger it probably doesn’t intercept synthetic method, although it allows me to register a replacement for `access$0` and a method’s existence is checked at registration. But the replacement is never invoked. – Erwin Bolwidt Jan 24 '18 at 00:43
18

Since this seems to be a follow-up of this JavaScript question, it’s worth noting that this trick and similar works in Java too:

public class Q48383521 {
    public static void main(String[] args) {
        int aᅠ = 1;
        int ᅠ2 = 3;
        int a = 3;
        if(aᅠ==1 && a==ᅠ2 && a==3) {
            System.out.println("success");
        }
    }
}

On Ideone


But note that this isn’t the worst thing you could do with Unicode. Using white-space or control characters that are valid identifiers parts or using different letters that look the same still creates identifiers that are different and can be spotted, e.g. when doing a text search.

But this program

public class Q48383521 {
    public static void main(String[] args) {
        int ä = 1;
        int ä = 2;
        if(ä == 1 && ä == 2) {
            System.out.println("success");
        }
    }
}

uses two identifiers that are the same, at least from the Unicode point of view. They just use different ways to encode the same character ä, using U+00E4 and U+0061 U+0308.

On Ideone

So depending on the tool you’re using, they may not only look the same, Unicode enabled text tools may not even report any difference, always finding both when searching. You may even have the problem that the different representations get lost when copying the source code to someone else, perhaps trying to get help for the “weird behavior”, making it non-reproducible for the helper.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • 3
    Eh, doesn't [this answer](https://stackoverflow.com/a/48385475/1898563) cover unicode abuse well enough? – Michael Jan 22 '18 at 16:50
  • 2
    `int ᅠ2 = 3;` is it intentional ? Because, I'm seeing very weird code all around – Ravi Jan 22 '18 at 16:52
  • 1
    @Michael not exactly, as that answer is about using two different letters (which IDEs would consider different when searching for `a`), whereas this is about white-space, and well, it’s giving credit to the even older answers on the related JavaScript question. Note that [my comment there](https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true/48274520#comment83575574_48274520) is even older than the Java question (by several days)… – Holger Jan 22 '18 at 16:52
  • @Ravi: yes, it’s based on [my even older comment](https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true/48274520#comment83575574_48274520) at the similar JavaScript question. – Holger Jan 22 '18 at 16:53
  • 2
    I don't see the distinction. Both answers are providing a solution where the three identifiers in the if statement are visually similar but technically distinct by virtue of using unusual unicode characters. Whether it's whitespace or Cyrillic is irrelevant. – Michael Jan 22 '18 at 17:41
  • 2
    @Michael you may see it that way, that’s up to you. As said, I wanted to state that the answer given five days ago for JavaScript also applies to Java, just considering the history of the question. Yes, that’s somewhat redundant to another answer which does not refer to the linked JavaScript question. Anyway, in the meanwhile I updated my answer to add a case that is not about visually similar characters, but different ways to encode *the same character* and it’s not even an “unusual unicode character”; it’s a character I’m using every day… – Holger Jan 22 '18 at 17:52
4

Inspired by the @Erwin's excellent answer, I wrote a similar example, but using Java Stream API.

And an interesting thing is that my solution works, but in very rare cases (because  just-in-time compiler optimizes such a code).

The trick is to disable any JIT optimizations using the following VM option:

-Djava.compiler=NONE

In this situation, the number of success cases increases significantly. Here is the code:

class Race {
    private static int a;

    public static void main(String[] args) {
        IntStream.range(0, 100_000).parallel().forEach(i -> {
            a = 1;
            a = 2;
            a = 3;
            testValue();
        });
    }

    private static void testValue() {
        if (a == 1 && a == 2 && a == 3) {
            System.out.println("Success");
        }
    }
}

P.S. Parallel streams use ForkJoinPool under the hood, and variable a is shared between multiple threads without any synchronization, that's why the result is non-deterministic.

Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
1

Along similar lines, by forcing a float (or double) to underflow (or overflow) through division (or multiplication) by a large number:

int a = 1;
if (a / Float.POSITIVE_INFINITY == 1 / Float.POSITIVE_INFINITY
        && a / Float.POSITIVE_INFINITY == 2 / Float.POSITIVE_INFINITY
        && a / Float.POSITIVE_INFINITY == 3 / Float.POSITIVE_INFINITY) {
    System.out.println("Success");
}
Aloke
  • 165
  • 6
  • 2
    @PatrickRoberts - this specific behaviour is floating point underflow as per the [Java docs](https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html). Also see [this](https://en.wikipedia.org/wiki/Arithmetic_underflow), [this](https://www.codeday.top/2017/08/14/33843.html), [this](https://stackoverflow.com/a/2154814) & [this](https://blog.webnersolutions.com/java-int-and-float-overflow-and-underflow-with-examples). – Aloke Jan 25 '18 at 09:19