2

Problem statement:

I am encountering an issue when running the following multi-threaded program. The program spawns a large number of threads (10,000) that process the same byte array value. The issue becomes more frequent under high CPU usage and when memory constraints are applied (e.g., setting -Xms32m -Xmx32m).

The method byteArrayToInt is supposed to convert a specific segment of the byte array into an integer. However, intermittently, it produces incorrect values. The expected value for liVersion is 1, but random values are being observed instead. This issue occurs even when the program is executed with sufficient memory and less number of threads (even single thread) but becomes significantly less frequent.

The integer conversion of 2nd to 4th value of pTestData which is [1, 0] should be 1, but it intermittently gives random values in the output.

Environment:

Operating system: Windows 10

Java version: Eclipse Temurin-17.0.10+11

Code snippet:

import java.util.Arrays;

public class TestMain
{
    private static int miParallelThreadCount = 10000;

        private static long mlExecutionIntervalInMillis=100;
        
    public static void main(String[] args)
    {
        System.out.println("Startin tornado at interval: " + mlExecutionIntervalInMillis + " with parallel threads: " + miParallelThreadCount);
        while(true)
        {
                        //Runs the test code to reproduce the issue
            runTornado();
            try
            {
                Thread.sleep(mlExecutionIntervalInMillis);
            } catch (Throwable lThrowable)
            {
                System.out.println("Task failed due to: " + lThrowable.getLocalizedMessage());
                lThrowable.printStackTrace();
            }
        }
    }

    private static void runTornado() 
    {   
        //Test byte array
        byte[] data = new byte[]
                { 65, 50, 1, 0, 1, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 16, 0, 53, -76, -66, 125, -115, 69, -111, 80, -81, -33, -62, 84, -59, -64, -114, 113, -92, -59, 37, 106, 85, -111, -100, -19, 114, 99, 18, -9, -62, -123, -75, -22, -40, 70, -70, -46, 119, 11, -17, -71, -93, -126, -28, 116, 104, -4, -45, -58, 121, 4, 50, 76, 46, 13, -91, -76, 37, -103, 101, 57, 54, 75, 83, -124 };
        
        for(int i=0; i<miParallelThreadCount; ++i)
        {
                //This snippet executes the group of compareInner methods in new threads
            new Thread(() -> 
            {
                try
                {
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                    compareInner(data, 0, data.length);
                } 
                catch (Throwable lThrowable) 
                {
                    System.out.println("Something went wrong: " + lThrowable.getLocalizedMessage());
                    lThrowable.printStackTrace();
                }
            }).start();
        }
        System.out.println("Ran tornado");
    }

    private static byte[] compareInner(byte[] pTestData, int pStartIndex, int pLength)
    {
                //Copies the pTestData into new array as it is
        byte[] lbarrData = Arrays.copyOfRange(pTestData, 0, 0 + pTestData.length);
               //copies only 2ndand 3rd element from the array which is [1, 0]
        byte[] lbarrVer = Arrays.copyOfRange(lbarrData, 2, 4);

               //Converts the array [1, 0] into integer, which should always return 1
        int liVersion = byteArrayToInt(lbarrVer);

        if(liVersion != 1)
        {
            System.out.println("Invalid Version : " + liVersion + " data array: " + Arrays.toString(lbarrData) +  " header array: " + Arrays.toString(lbarrVer));
        }
        
        return lbarrData;
    }
    
    public static final int byteArrayToInt(byte[] pSource)
    {
        int lValue = 0;
        for (int i = 0; i < pSource.length; i++)
        {
            lValue += (pSource[i] & 0xff) << (8 * i);
        }
        return lValue;
    }
}
  • I tried running this code with 32m xms and xmx, issue is reproducible.
  • Issue is reproducible even when xms and xmx is 1024 but less frequent.
  • Issue is seen in single thread (miParallelThreadCount = 1) but is less frequent.
  • Issue has not been observed when taken a debug on the code.
  • Issue is not observed when a "compareInner(enc, 0, enc.length);" method is called only once per thread execution.
  • Issue is not observed on AdoptOpenJDK 11.0.11 yet.

I have also reproduced the issue in Eclipse Temurin-17.0.13+11:

enter image description here

Edit 2: I was also able to reproduce the issue in Amazon corretto 17, Please find the below output:

enter image description here

Also, reference link for the discussions in the eclipse temurin support github: https://github.com/adoptium/adoptium-support/issues/1209

5
  • Not reproducible; you're on an old and unsupported version. Commented Dec 24, 2024 at 19:50
  • Hi @rzwitserloot, I have tried this on AdoptOpenJDK 17.0.13 as well and its reproducible. Please give it some time after the script is executed or try re-executing it as the issue is intermittent and may not surface on the first try. Commented Dec 26, 2024 at 6:29
  • 1
    AdoptOpenJDK stopped a few years ago, you need to switch to Eclipse Adoptium (the successor to the AdoptOpenJDK project). Though if you're using 17.0.13, it sounds like you're not even using AdoptOpenJDK anyway, because that project stopped long before that version was ever released. Commented Dec 26, 2024 at 13:13
  • Hi @MarkRotteveel, yes you are correct, the version is actually 'Eclipse Temurin-17.0.10+11, have updated in the question. Commented Dec 27, 2024 at 6:01
  • 1
    @AmeySawant Ran it for an hour, never a problem (AARCH architecture, current version) - which isn't surprising, you indicated that it's not reproducible on modern VMs. After inspecting the code thoroughly I conclude: You've found a bug. It happens. Reporting it is difficult (as it depends on many factors), you might want to ask the VM to dump its hotspotted code or try it in -Xint mode to see if it happens without hotspot, but, mostly: Pointless. You can't report bugs like this against anything but the most recent version. Commented Dec 28, 2024 at 7:10

1 Answer 1

0

I am able to reproduce this with 17.0.13 as well. It gets reproduced in first few executions only.

  • header array is always printed as [1, 0]
  • looks CPU computations not behaving as expected when doing the left shift or "&" operation in (pSource[i] & 0xff) << (8 * i)
Sign up to request clarification or add additional context in comments.

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.