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;

Reply via email to