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

Mike Duigou mike.duigou at oracle.com
Fri Feb 17 16:57:25 UTC 2012


Throwing plain Error could probably be improved to InternalError.

(Though it will probably never be thrown).

Mike

On Feb 17 2012, at 04:00 , Rémi Forax wrote:

> 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