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