From a1869cb4a18b12f4c5a1bb6b69f8b0da24c28f73 Mon Sep 17 00:00:00 2001 From: hpi1 Date: Tue, 16 Apr 2019 12:37:13 +0300 Subject: [PATCH] Java 8+: Unconditionally hook java.io.FileSystem class This is done during JVM boot stage => unsupported FileSystem implementation will prevent JVM boot. Fixes skipping wrapper class sometimes when java.io.File.fs is static final. --- .../bdj/java/java/io/BDFileSystem.java | 27 +++++----- .../bdj/java/java/io/DefaultFileSystem.java | 51 +++++++++++++++++++ 2 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 src/libbluray/bdj/java/java/io/DefaultFileSystem.java diff --git a/src/libbluray/bdj/java/java/io/BDFileSystem.java b/src/libbluray/bdj/java/java/io/BDFileSystem.java index aaa7d824..0ade43e0 100644 --- a/src/libbluray/bdj/java/java/io/BDFileSystem.java +++ b/src/libbluray/bdj/java/java/io/BDFileSystem.java @@ -50,18 +50,17 @@ public abstract class BDFileSystem extends FileSystem { private static FileSystem nativeFileSystem; static { - /* Java 8: getFileSystem() no longer exists on java.io.FileSystem */ try { - nativeFileSystem = (FileSystem)Class.forName("java.io.DefaultFileSystem") - .getDeclaredMethod("getFileSystem", new Class[0]) + /* Java < 8 */ + nativeFileSystem = (FileSystem)FileSystem.class + .getDeclaredMethod("getFileSystem",new Class[0]) .invoke(null, new Object[0]); } catch (Exception e) { try { - nativeFileSystem = (FileSystem)FileSystem.class - .getDeclaredMethod("getFileSystem",new Class[0]) - .invoke(null, new Object[0]); - } catch (Exception t) { - System.err.print("Couldn't find native filesystem: " + t); + /* Just use our wrapper. If it fails, JVM won't be booted anyway ... */ + nativeFileSystem = DefaultFileSystem.getNativeFileSystem(); + } catch (Throwable t) { + System.err.print("Couldn't find native filesystem: " + e); } } } @@ -77,7 +76,7 @@ public abstract class BDFileSystem extends FileSystem { } /* - * Replace File.fs for Xlets + * Replace File.fs for Xlets (required with Java < 8 where this is not done unconditionally) * * (called by org.videolan.BDJClassLoader) */ @@ -101,15 +100,15 @@ public abstract class BDFileSystem extends FileSystem { filesystem = c.getDeclaredField("fs"); filesystem.setAccessible(true); - /* Java 8: remove "final" modifier from the field */ - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(filesystem, filesystem.getModifiers() & ~Modifier.FINAL); - FileSystem fs = (FileSystem)filesystem.get(null); if (fs instanceof BDFileSystemImpl) { //System.err.print("FileSystem already wrapped"); } else { + /* Java 8: we should never end up here ... */ + /* Java 8: remove "final" modifier from the field */ + //Field modifiersField = Field.class.getDeclaredField("modifiers"); + //modifiersField.setAccessible(true); + //modifiersField.setInt(filesystem, filesystem.getModifiers() & ~Modifier.FINAL); filesystem.set(null, new BDFileSystemImpl(fs)); } } catch (Exception t) { diff --git a/src/libbluray/bdj/java/java/io/DefaultFileSystem.java b/src/libbluray/bdj/java/java/io/DefaultFileSystem.java new file mode 100644 index 00000000..8663128e --- /dev/null +++ b/src/libbluray/bdj/java/java/io/DefaultFileSystem.java @@ -0,0 +1,51 @@ +/* + * This file is part of libbluray + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + */ + +package java.io; + +class DefaultFileSystem { + + static FileSystem getNativeFileSystem() { + Exception e1, e2, e3; + try { + return (FileSystem)Class.forName(System.getProperty("org.videolan.bdj_filesystem")).newInstance(); + } catch (Exception e) { + e3 = e; + } + try { + return (FileSystem)Class.forName("java.io.UnixFileSystem").newInstance(); + } catch (Exception e) { + e1 = e; + } + try { + return (FileSystem)Class.forName("java.io.WinNTFileSystem").newInstance(); + } catch (Exception e) { + e2 = e; + } + + /* No way to recover from here */ + System.err.println("Unsupported native filesystem !\n\t" + e1 + "\n\t" + e2 + "\n\t" + e3); + //Runtime.getRuntime().halt(-1); + throw new Error("No filesystem implementation found"); + } + + public static FileSystem getFileSystem() { + FileSystem nativeFs = getNativeFileSystem(); + return new BDFileSystemImpl(nativeFs); + } +}