java.io.File field "path" is not declared final

Rémi Forax forax at univ-mlv.fr
Fri Feb 17 12:00:27 UTC 2012


On 02/17/2012 12:36 PM, Rémi Forax wrote:
> On 02/16/2012 11:37 AM, Alan Bateman wrote:
>> On 15/02/2012 17:34, Rémi Forax wrote:
>>> Reported by a user on the concurrency-interest mailing list,
>>> File field "path" is not declared final but should be.
>> Thanks for forwarding Rémi. I did reply on concurrency-interest but I 
>> forgot that my original subscription there was @sun.com.
>>
>> I've created a bug to track this:
>>
>> 7146152: File.path should be final
>>
>> It's something that should have been fixed a long time ago (it's 
>> always been non-final). It's just the readObject that requires work, 
>> to use unsafe as you suggest.
>>
>> -Alan
>
> Hi Alan, hi all,
> here is a possible fix.
>
> Rémi
>
Better with the attachment inlined :)

Rémi

diff --git a/src/share/classes/java/io/File.java 
b/src/share/classes/java/io/File.java
--- a/src/share/classes/java/io/File.java
+++ b/src/share/classes/java/io/File.java
@@ -153,7 +153,7 @@
      /**
       * The FileSystem object representing the platform's local file 
system.
       */
-    static private FileSystem fs = FileSystem.getFileSystem();
+    private static final FileSystem fs = FileSystem.getFileSystem();

      /**
       * This abstract pathname's normalized pathname string.  A normalized
@@ -162,13 +162,13 @@
       *
       * @serial
       */
-    private String path;
+    private final String path;

      /**
       * The length of this abstract pathname's prefix, or zero if it has no
       * prefix.
       */
-    private transient int prefixLength;
+    private final transient int prefixLength;

      /**
       * Returns the length of this abstract pathname's prefix.
@@ -2023,10 +2023,28 @@
          char sep = s.readChar(); // read the previous separator char
          if (sep != separatorChar)
              pathField = pathField.replace(sep, separatorChar);
-        this.path = fs.normalize(pathField);
-        this.prefixLength = fs.prefixLength(this.path);
+        String path = fs.normalize(pathField);
+        UNSAFE.putObject(this, PATH_OFFSET, path);
+        UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, 
fs.prefixLength(path));
      }

+    private static final long PATH_OFFSET;
+    private static final long PREFIX_LENGTH_OFFSET;
+    private static final sun.misc.Unsafe UNSAFE;
+    static {
+        try {
+            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+            PATH_OFFSET = unsafe.objectFieldOffset(
+                    File.class.getDeclaredField("path"));
+            PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(
+                    File.class.getDeclaredField("prefixLength"));
+            UNSAFE = unsafe;
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+    }
+
+
      /** use serialVersionUID from JDK 1.0.2 for interoperability */
      private static final long serialVersionUID = 301077366599181567L;




More information about the core-libs-dev mailing list