1 2 Previous Next 26 Replies Latest reply on Feb 5, 2009 10:39 AM by clebert.suconic

    UUIDGenerator broken on Windows...

    clebert.suconic

       

      public final UUID generateTimeBasedUUID(byte[] byteAddr)
       {
       byte[] contents = new byte[16];
       int pos = 12;
       for (int i = 0; i < 4; ++i)
       {
       contents[pos + i] = byteAddr; <<-- NPE on byteAddr
       }
      



      It only happens on Windows.

      byteAddr is null.

        • 1. Re: UUIDGenerator broken on Windows...
          timfox

          Can you show a complete test case?

          • 2. Re: UUIDGenerator broken on Windows...
            clebert.suconic

            Actually.. It is ArrayIndexOutOfBoundException...

            getHardwareAddress is returning a byte[0];

            • 3. Re: UUIDGenerator broken on Windows...
              timfox

              The only way that could possibly fail is if the byte[] byteAddr was less than 16

              • 4. Re: UUIDGenerator broken on Windows...
                clebert.suconic

                 

                "timfox" wrote:
                Can you show a complete test case?


                I" m just running UUIDTest on Windows.

                • 5. Re: UUIDGenerator broken on Windows...
                  timfox

                  Ok, so this is a bug in Jeff's network address code. It should never return a zero length byte[]

                  • 6. Re: UUIDGenerator broken on Windows...
                    clebert.suconic

                     

                    "timfox" wrote:
                    The only way that could possibly fail is if the byte[] byteAddr was less than 16



                    Yep... and it is returning byteArray[0] on my Windows.

                    • 7. Re: UUIDGenerator broken on Windows...
                      timfox

                      Guess... you could probably fix this by checking for zero length byte[] in getHardwareAddress() and returning null.

                      • 8. Re: UUIDGenerator broken on Windows...
                        timfox

                        BTW - are you running in a security manager?

                        If not, then I am surprised getNetworkInterfaces() doesn't return any real interfaces.... that might point to a real bug, or issue in the Windows implementation of said function.

                        • 9. Re: UUIDGenerator broken on Windows...
                          clebert.suconic

                          No SecurityManager.. I'm just running the test inside Eclipse on Windows.


                          I've added some hacking around getHardwareAddress, to discard anything that had address.length == 0.

                          My windows returned an address with 6 bytes then. At that point I got an outOfMemoryError, while calilng UUID.toString. (i.e. the code was in loop)


                          Then I rejected everything that had length != 16... it eventually returned null, and I got the infinite loop throwing an OME again.

                          • 10. Re: UUIDGenerator broken on Windows...
                            clebert.suconic

                            i.e. There is an issue on the Windows implementation.

                            • 11. Re: UUIDGenerator broken on Windows...
                              clebert.suconic

                              Actually, I made the test to pass, by changing the method as this:

                              public final static byte[] getHardwareAddress()
                               {
                               Method getHardwareAddressMethod;
                               try
                               {
                               getHardwareAddressMethod = NetworkInterface.class.getMethod("getHardwareAddress", null);
                               }
                               catch (Throwable t)
                               {
                               // not on Java 6 or not enough security permission
                               return null;
                               }
                              
                               try
                               {
                               Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
                               while (networkInterfaces.hasMoreElements())
                               {
                               NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
                               Object res = getHardwareAddressMethod.invoke(networkInterface, null);
                               if (res instanceof byte[])
                               {
                               byte[] address = (byte[])res;
                               if (address.length == 16)
                               {
                               if (log.isDebugEnabled())
                               {
                               log.debug("using hardware address " + asString(address));
                               }
                               return address;
                               }
                               }
                               }
                               }
                               catch (Throwable t)
                               {
                               }
                              
                               return null;
                               }
                              


                              But this is aways returning null on windows.

                              But I still have an OME on timing.UUIDTest, but it is not caused by an infinite loop as I though.

                              • 12. Re: UUIDGenerator broken on Windows...
                                clebert.suconic

                                 

                                "timfox" wrote:
                                Guess... you could probably fix this by checking for zero length byte[] in getHardwareAddress() and returning null.


                                Just saw this post...

                                yes, This is how I fixed it (see my previous post).. but I will let Jeff decide if it should be committed or if he can think of another way of fixing it.

                                • 13. Re: UUIDGenerator broken on Windows...
                                  timfox

                                  aha. my guess is you're using ipv6 so the address returned is not length 16!

                                  • 14. Re: UUIDGenerator broken on Windows...
                                    jmesnil

                                    in UUIDGenerator.generateTimeBasedUUID, we use only the 1st 4 bytes of the address so that it works with IPv4 (4 bytes), IPv4 (16 bytes) and MAC (6 bytes).

                                    The check on getHardwareAddress should be (address.length >= 4) so that we can safely use the byte array.

                                    However, I'm surprised that Windows returns a 0-sized array.

                                    Clebert, could you run this code on Java *6* on Windows to check what it returns:

                                    public static void main(String[] args) throws SocketException
                                     {
                                    
                                     Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
                                     while (networkInterfaces.hasMoreElements())
                                     {
                                     NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
                                     byte[] hardwareAddress = networkInterface.getHardwareAddress();
                                     if (hardwareAddress == null)
                                     {
                                     System.out.println(networkInterface.getDisplayName() + ":null");
                                     } else
                                     {
                                     String s = "";
                                     for (int i = 0; i < hardwareAddress.length - 1; i++)
                                     {
                                     s += Integer.toHexString(hardwareAddress) + ":";
                                     }
                                     s += hardwareAddress[hardwareAddress.length - 1];
                                     System.out.println(networkInterface.getDisplayName() + ":" + s);
                                     }
                                     }
                                     }


                                    1 2 Previous Next