diff --git a/src/java.desktop/share/classes/sun/font/FileFontStrike.java b/src/java.desktop/share/classes/sun/font/FileFontStrike.java
index bf98b8ca57863..e6d07026a55bc 100644
--- a/src/java.desktop/share/classes/sun/font/FileFontStrike.java
+++ b/src/java.desktop/share/classes/sun/font/FileFontStrike.java
@@ -315,8 +315,7 @@ long getGlyphImageFromWindows(int glyphCode) {
              * work to the FM case.
              */
             float advance = getGlyphAdvance(glyphCode, false);
-            StrikeCache.unsafe.putFloat(ptr + StrikeCache.xAdvanceOffset,
-                                        advance);
+            StrikeCache.setGlyphXAdvance(ptr, advance);
             return ptr;
         } else {
             if (FontUtilities.isLogging()) {
@@ -665,8 +664,7 @@ private float getGlyphAdvance(int glyphCode, boolean getUserAdv) {
                 glyphPtr = getCachedGlyphPtr(glyphCode);
             }
             if (glyphPtr != 0L) {
-                advance = StrikeCache.unsafe.getFloat
-                    (glyphPtr + StrikeCache.xAdvanceOffset);
+                advance = StrikeCache.getGlyphXAdvance(glyphPtr);
 
             } else {
                 advance = fileFont.getGlyphAdvance(pScalerContext, glyphCode);
@@ -726,15 +724,13 @@ void getGlyphImageBounds(int glyphCode, Point2D.Float pt,
             return;
         }
 
-        topLeftX = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftXOffset);
-        topLeftY = StrikeCache.unsafe.getFloat(ptr+StrikeCache.topLeftYOffset);
+        topLeftX = StrikeCache.getGlyphTopLeftX(ptr);
+        topLeftY = StrikeCache.getGlyphTopLeftY(ptr);
 
         result.x = (int)Math.floor(pt.x + topLeftX + 0.5f);
         result.y = (int)Math.floor(pt.y + topLeftY + 0.5f);
-        result.width =
-            StrikeCache.unsafe.getShort(ptr+StrikeCache.widthOffset)  &0x0ffff;
-        result.height =
-            StrikeCache.unsafe.getShort(ptr+StrikeCache.heightOffset) &0x0ffff;
+        result.width = StrikeCache.getGlyphWidth(ptr) & 0x0ffff;
+        result.height = StrikeCache.getGlyphHeight(ptr) & 0x0ffff;
 
         /* HRGB LCD text may have padding that is empty. This is almost always
          * going to be when topLeftX is -2 or less.
@@ -755,25 +751,22 @@ void getGlyphImageBounds(int glyphCode, Point2D.Float pt,
 
     private int getGlyphImageMinX(long ptr, int origMinX) {
 
-        int width = StrikeCache.unsafe.getChar(ptr+StrikeCache.widthOffset);
-        int height = StrikeCache.unsafe.getChar(ptr+StrikeCache.heightOffset);
-        int rowBytes =
-            StrikeCache.unsafe.getChar(ptr+StrikeCache.rowBytesOffset);
+        int width = StrikeCache.getGlyphWidth(ptr);
+        int height = StrikeCache.getGlyphHeight(ptr);
+        int rowBytes = StrikeCache.getGlyphRowBytes(ptr);
 
         if (rowBytes == width) {
             return origMinX;
         }
 
-        long pixelData =
-            StrikeCache.unsafe.getAddress(ptr + StrikeCache.pixelDataOffset);
-
-        if (pixelData == 0L) {
+        if (StrikeCache.getGlyphImagePtr(ptr) == 0L) {
             return origMinX;
         }
 
+        byte[] pixelData = StrikeCache.getGlyphPixelBytes(ptr);
         for (int y=0;y<height;y++) {
             for (int x=0;x<3;x++) {
-                if (StrikeCache.unsafe.getByte(pixelData+y*rowBytes+x) != 0) {
+                if (pixelData[(y*rowBytes)+x] != 0) {
                     return origMinX;
                 }
             }
@@ -819,10 +812,8 @@ private Point2D.Float getGlyphMetrics(int glyphCode, boolean getImage) {
         }
         if (glyphPtr != 0L) {
             metrics = new Point2D.Float();
-            metrics.x = StrikeCache.unsafe.getFloat
-                (glyphPtr + StrikeCache.xAdvanceOffset);
-            metrics.y = StrikeCache.unsafe.getFloat
-                (glyphPtr + StrikeCache.yAdvanceOffset);
+            metrics.x = StrikeCache.getGlyphXAdvance(glyphPtr);
+            metrics.y = StrikeCache.getGlyphYAdvance(glyphPtr);
             /* advance is currently in device space, need to convert back
              * into user space.
              * This must not include the translation component. */
diff --git a/src/java.desktop/share/classes/sun/font/GlyphList.java b/src/java.desktop/share/classes/sun/font/GlyphList.java
index 8d19d005b89d3..df6ca08586cf0 100644
--- a/src/java.desktop/share/classes/sun/font/GlyphList.java
+++ b/src/java.desktop/share/classes/sun/font/GlyphList.java
@@ -319,10 +319,9 @@ public void setGlyphIndex(int i) {
            metrics[4] = 0;
            return;
         }
-        float gx =
-            StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftXOffset);
-        float gy =
-            StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftYOffset);
+
+        float gx = StrikeCache.getGlyphTopLeftX(images[i]);
+        float gy = StrikeCache.getGlyphTopLeftY(images[i]);
 
         if (usePositions) {
             metrics[0] = (int)Math.floor(positions[(i<<1)]   + gposx + gx);
@@ -331,17 +330,12 @@ public void setGlyphIndex(int i) {
             metrics[0] = (int)Math.floor(gposx + gx);
             metrics[1] = (int)Math.floor(gposy + gy);
             /* gposx and gposy are used to accumulate the advance */
-            gposx += StrikeCache.unsafe.getFloat
-                (images[i]+StrikeCache.xAdvanceOffset);
-            gposy += StrikeCache.unsafe.getFloat
-                (images[i]+StrikeCache.yAdvanceOffset);
+            gposx += StrikeCache.getGlyphXAdvance(images[i]);
+            gposy += StrikeCache.getGlyphYAdvance(images[i]);
         }
-        metrics[2] =
-            StrikeCache.unsafe.getChar(images[i]+StrikeCache.widthOffset);
-        metrics[3] =
-            StrikeCache.unsafe.getChar(images[i]+StrikeCache.heightOffset);
-        metrics[4] =
-            StrikeCache.unsafe.getChar(images[i]+StrikeCache.rowBytesOffset);
+        metrics[2] = StrikeCache.getGlyphWidth(images[i]);
+        metrics[3] = StrikeCache.getGlyphHeight(images[i]);
+        metrics[4] = StrikeCache.getGlyphRowBytes(images[i]);
     }
 
     public int[] getMetrics() {
@@ -360,22 +354,12 @@ public byte[] getGrayBits() {
         if (images[glyphindex] == 0L) {
             return graybits;
         }
-        long pixelDataAddress =
-            StrikeCache.unsafe.getAddress(images[glyphindex] +
-                                          StrikeCache.pixelDataOffset);
-
+        long pixelDataAddress = StrikeCache.getGlyphImagePtr(images[glyphindex]);
         if (pixelDataAddress == 0L) {
             return graybits;
         }
-        /* unsafe is supposed to be fast, but I doubt if this loop can beat
-         * a native call which does a getPrimitiveArrayCritical and a
-         * memcpy for the typical amount of image data (30-150 bytes)
-         * Consider a native method if there is a performance problem (which
-         * I haven't seen so far).
-         */
-        for (int i=0; i<len; i++) {
-            graybits[i] = StrikeCache.unsafe.getByte(pixelDataAddress+i);
-        }
+        byte[] bytes = StrikeCache.getGlyphPixelBytes(images[glyphindex]);
+        System.arraycopy(bytes, 0, graybits, 0, bytes.length);
         return graybits;
     }
 
@@ -445,13 +429,6 @@ public int getNumGlyphs() {
      * but it seems unavoidable without re-working the Java TextRenderers.
      */
     private void fillBounds(int[] bounds, int endGlyphIndex) {
-        /* Faster to access local variables in the for loop? */
-        int xOffset = StrikeCache.topLeftXOffset;
-        int yOffset = StrikeCache.topLeftYOffset;
-        int wOffset = StrikeCache.widthOffset;
-        int hOffset = StrikeCache.heightOffset;
-        int xAdvOffset = StrikeCache.xAdvanceOffset;
-        int yAdvOffset = StrikeCache.yAdvanceOffset;
 
         int startGlyphIndex = glyphindex + 1;
         if (startGlyphIndex >= endGlyphIndex) {
@@ -471,10 +448,10 @@ private void fillBounds(int[] bounds, int endGlyphIndex) {
             if (images[i] == 0L) {
                 continue;
             }
-            gx = StrikeCache.unsafe.getFloat(images[i]+xOffset);
-            gy = StrikeCache.unsafe.getFloat(images[i]+yOffset);
-            gw = StrikeCache.unsafe.getChar(images[i]+wOffset);
-            gh = StrikeCache.unsafe.getChar(images[i]+hOffset);
+            gx = StrikeCache.getGlyphTopLeftX(images[i]);
+            gy = StrikeCache.getGlyphTopLeftY(images[i]);
+            gw = StrikeCache.getGlyphWidth(images[i]);
+            gh = StrikeCache.getGlyphHeight(images[i]);
 
             if (usePositions) {
                 gx0 = positions[posIndex++] + gx + glx;
@@ -482,8 +459,8 @@ private void fillBounds(int[] bounds, int endGlyphIndex) {
             } else {
                 gx0 = glx + gx;
                 gy0 = gly + gy;
-                glx += StrikeCache.unsafe.getFloat(images[i]+xAdvOffset);
-                gly += StrikeCache.unsafe.getFloat(images[i]+yAdvOffset);
+                glx += StrikeCache.getGlyphXAdvance(images[i]);
+                gly += StrikeCache.getGlyphYAdvance(images[i]);
             }
             gx1 = gx0 + gw;
             gy1 = gy0 + gh;
@@ -506,10 +483,8 @@ public static boolean canContainColorGlyphs() {
     }
 
     public boolean isColorGlyph(int glyphIndex) {
-        int width = StrikeCache.unsafe.getChar(images[glyphIndex] +
-                                               StrikeCache.widthOffset);
-        int rowBytes = StrikeCache.unsafe.getChar(images[glyphIndex] +
-                                                  StrikeCache.rowBytesOffset);
+        int width = StrikeCache.getGlyphWidth(images[glyphIndex]);
+        int rowBytes = StrikeCache.getGlyphRowBytes(images[glyphIndex]);
         return rowBytes == width * 4;
     }
 
diff --git a/src/java.desktop/share/classes/sun/font/StrikeCache.java b/src/java.desktop/share/classes/sun/font/StrikeCache.java
index 950ba5b3d465b..ea1369b4383ac 100644
--- a/src/java.desktop/share/classes/sun/font/StrikeCache.java
+++ b/src/java.desktop/share/classes/sun/font/StrikeCache.java
@@ -27,6 +27,16 @@
 
 import java.awt.GraphicsConfiguration;
 import java.awt.GraphicsEnvironment;
+
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import static java.lang.foreign.MemorySegment.NULL;
+import java.lang.foreign.StructLayout;
+import java.lang.foreign.ValueLayout;
+import static java.lang.foreign.ValueLayout.*;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
@@ -37,7 +47,6 @@
 import sun.java2d.pipe.BufferedContext;
 import sun.java2d.pipe.RenderQueue;
 import sun.java2d.pipe.hw.AccelGraphicsConfig;
-import jdk.internal.misc.Unsafe;
 
 /**
 
@@ -63,8 +72,6 @@
 
 public final class StrikeCache {
 
-    static final Unsafe unsafe = Unsafe.getUnsafe();
-
     static ReferenceQueue<Object> refQueue = Disposer.getQueue();
 
     static ArrayList<GlyphDisposedListener> disposeListeners = new ArrayList<GlyphDisposedListener>(1);
@@ -98,40 +105,159 @@ public final class StrikeCache {
     static boolean cacheRefTypeWeak;
 
     /*
-     * Native sizes and offsets for glyph cache
-     * There are 10 values.
+     * Native sizes and accessors for glyph cache structure.
+     * There are 10 values. Also need native address size and a long which
+     * references a memory address for a "null" glyph image.
      */
-    static int nativeAddressSize;
-    static int glyphInfoSize;
-    static int xAdvanceOffset;
-    static int yAdvanceOffset;
-    static int boundsOffset;
-    static int widthOffset;
-    static int heightOffset;
-    static int rowBytesOffset;
-    static int topLeftXOffset;
-    static int topLeftYOffset;
-    static int pixelDataOffset;
-    static int cacheCellOffset;
-    static int managedOffset;
-    static long invisibleGlyphPtr;
-
-    /* Native method used to return information used for unsafe
-     * access to native data.
-     * return values as follows:-
-     * arr[0] = size of an address/pointer.
-     * arr[1] = size of a GlyphInfo
-     * arr[2] = offset of advanceX
-     * arr[3] = offset of advanceY
-     * arr[4] = offset of width
-     * arr[5] = offset of height
-     * arr[6] = offset of rowBytes
-     * arr[7] = offset of topLeftX
-     * arr[8] = offset of topLeftY
-     * arr[9] = offset of pixel data.
-     * arr[10] = address of a GlyphImageRef representing the invisible glyph
-     */
-    static native void getGlyphCacheDescription(long[] infoArray);
+    static final int nativeAddressSize = (int)ValueLayout.ADDRESS.byteSize();
+    static final long invisibleGlyphPtr = getInvisibleGlyphPtr(); // a singleton.
+
+    static native long getInvisibleGlyphPtr();
+
+    public static final StructLayout GlyphImageLayout = MemoryLayout.structLayout(
+        JAVA_FLOAT.withName("xAdvance"), // 0+4=4,
+        JAVA_FLOAT.withName("yAdvance"), // 4+4=8,
+        JAVA_CHAR.withName("width"),     // 8+2=10,
+        JAVA_CHAR.withName("height"),    // 10+2=12
+        JAVA_CHAR.withName("rowBytes"),  // 12+2=14
+        JAVA_BYTE.withName("managed"),   // 14+1=15
+        MemoryLayout.paddingLayout(1),   // 15+1=16
+        JAVA_FLOAT.withName("topLeftX"), // 16+4=20
+        JAVA_FLOAT.withName("topLeftY"), // 20+4=24
+        ADDRESS.withName("cellInfo"),    // 24+8=32
+        ADDRESS.withName("image")        // 32+8=40
+     );
+
+   private static final long GLYPHIMAGESIZE = GlyphImageLayout.byteSize();
+
+   private static VarHandle getVarHandle(StructLayout struct, String name) {
+        VarHandle h = struct.varHandle(PathElement.groupElement(name));
+        /* insert 0 offset so don't need to pass arg every time */
+        return MethodHandles.insertCoordinates(h, 1, 0L).withInvokeExactBehavior();
+    }
+
+    private static final VarHandle xAdvanceHandle = getVarHandle(GlyphImageLayout, "xAdvance");
+    private static final VarHandle yAdvanceHandle = getVarHandle(GlyphImageLayout, "yAdvance");
+    private static final VarHandle widthHandle    = getVarHandle(GlyphImageLayout, "width");
+    private static final VarHandle heightHandle   = getVarHandle(GlyphImageLayout, "height");
+    private static final VarHandle rowBytesHandle = getVarHandle(GlyphImageLayout, "rowBytes");
+    private static final VarHandle managedHandle  = getVarHandle(GlyphImageLayout, "managed");
+    private static final VarHandle topLeftXHandle = getVarHandle(GlyphImageLayout, "topLeftX");
+    private static final VarHandle topLeftYHandle = getVarHandle(GlyphImageLayout, "topLeftY");
+    private static final VarHandle cellInfoHandle = getVarHandle(GlyphImageLayout, "cellInfo");
+    private static final VarHandle imageHandle    = getVarHandle(GlyphImageLayout, "image");
+
+    @SuppressWarnings("restricted")
+    static final float getGlyphXAdvance(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (float)xAdvanceHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final void setGlyphXAdvance(long ptr, float val) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        xAdvanceHandle.set(seg, val);
+    }
+
+    @SuppressWarnings("restricted")
+    static final float getGlyphYAdvance(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (float)yAdvanceHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final char getGlyphWidth(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (char)widthHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final char getGlyphHeight(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (char)heightHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final char getGlyphRowBytes(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (char)rowBytesHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final byte getGlyphManaged(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (byte)managedHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final float getGlyphTopLeftX(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (float)topLeftXHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final float getGlyphTopLeftY(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return (float)topLeftYHandle.get(seg);
+    }
+
+    @SuppressWarnings("restricted")
+    static final long getGlyphCellInfo(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return ((MemorySegment)cellInfoHandle.get(seg)).address();
+    }
+
+    @SuppressWarnings("restricted")
+    static final void setGlyphCellInfo(long ptr, long val) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        MemorySegment segval = MemorySegment.ofAddress(val);
+        cellInfoHandle.set(seg, segval);
+    }
+
+    @SuppressWarnings("restricted")
+    static final long getGlyphImagePtr(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        return ((MemorySegment)imageHandle.get(seg)).address();
+    }
+
+    @SuppressWarnings("restricted")
+    static final MemorySegment getGlyphPixelData(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        char hgt = (char)heightHandle.get(seg);
+        char rb = (char)rowBytesHandle.get(seg);
+        MemorySegment pixelData = (MemorySegment)imageHandle.get(seg);
+        pixelData = pixelData.reinterpret(rb * hgt);
+        return pixelData;
+    }
+
+    @SuppressWarnings("restricted")
+    static final byte[] getGlyphPixelBytes(long ptr) {
+        MemorySegment seg = MemorySegment.ofAddress(ptr);
+        seg = seg.reinterpret(GLYPHIMAGESIZE);
+        char hgt = (char)heightHandle.get(seg);
+        char rb = (char)rowBytesHandle.get(seg);
+        MemorySegment pixelData = (MemorySegment)imageHandle.get(seg);
+        int sz = rb * hgt;
+        pixelData = pixelData.reinterpret(sz);
+        return pixelData.toArray(ValueLayout.JAVA_BYTE);
+    }
+
+    static final byte getPixelByte(MemorySegment pixelData, long index) {
+       return pixelData.getAtIndex(JAVA_BYTE, index);
+    }
 
     static {
         initStatic();
@@ -140,24 +266,6 @@ public final class StrikeCache {
     @SuppressWarnings("removal")
     private static void initStatic() {
 
-        long[] nativeInfo = new long[13];
-        getGlyphCacheDescription(nativeInfo);
-        //Can also get address size from Unsafe class :-
-        //nativeAddressSize = unsafe.addressSize();
-        nativeAddressSize = (int)nativeInfo[0];
-        glyphInfoSize     = (int)nativeInfo[1];
-        xAdvanceOffset    = (int)nativeInfo[2];
-        yAdvanceOffset    = (int)nativeInfo[3];
-        widthOffset       = (int)nativeInfo[4];
-        heightOffset      = (int)nativeInfo[5];
-        rowBytesOffset    = (int)nativeInfo[6];
-        topLeftXOffset    = (int)nativeInfo[7];
-        topLeftYOffset    = (int)nativeInfo[8];
-        pixelDataOffset   = (int)nativeInfo[9];
-        invisibleGlyphPtr = nativeInfo[10];
-        cacheCellOffset = (int) nativeInfo[11];
-        managedOffset = (int) nativeInfo[12];
-
         if (nativeAddressSize < 4) {
             throw new InternalError("Unexpected address size for font data: " +
                                     nativeAddressSize);
@@ -324,7 +432,7 @@ private static void freeCachedIntMemory(int[] glyphPtrs, long pContext) {
                 ArrayList<Long> gids = null;
 
                 for (int i = 0; i < glyphPtrs.length; i++) {
-                    if (glyphPtrs[i] != 0 && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0) {
+                    if ((glyphPtrs[i] != 0) && getGlyphManaged(glyphPtrs[i]) == 0) {
 
                         if (gids == null) {
                             gids = new ArrayList<Long>();
@@ -350,8 +458,7 @@ private static void  freeCachedLongMemory(long[] glyphPtrs, long pContext) {
                 ArrayList<Long> gids = null;
 
                 for (int i=0; i < glyphPtrs.length; i++) {
-                    if (glyphPtrs[i] != 0
-                            && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0) {
+                    if ((glyphPtrs[i] != 0) && getGlyphManaged(glyphPtrs[i]) == 0) {
 
                         if (gids == null) {
                             gids = new ArrayList<Long>();
diff --git a/src/java.desktop/share/native/libfontmanager/sunFont.c b/src/java.desktop/share/native/libfontmanager/sunFont.c
index b50a67e5c40b0..6029dc02d89b8 100644
--- a/src/java.desktop/share/native/libfontmanager/sunFont.c
+++ b/src/java.desktop/share/native/libfontmanager/sunFont.c
@@ -300,41 +300,9 @@ JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory
     }
 }
 
-JNIEXPORT void JNICALL
-Java_sun_font_StrikeCache_getGlyphCacheDescription
-  (JNIEnv *env, jclass cls, jlongArray results) {
-
-    jlong* nresults;
-    GlyphInfo *info;
-    size_t baseAddr;
-
-    if ((*env)->GetArrayLength(env, results) < 13) {
-        return;
-    }
+JNIEXPORT jlong JNICALL
+Java_sun_font_StrikeCache_getInvisibleGlyphPtr(JNIEnv *env, jclass cls) {
 
-    nresults = (jlong*)(*env)->GetPrimitiveArrayCritical(env, results, NULL);
-    if (nresults == NULL) {
-        return;
-    }
-    info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo));
-    if (info == NULL) {
-        (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
-        return;
-    }
-    baseAddr = (size_t)info;
-    nresults[0] = sizeof(void*);
-    nresults[1] = sizeof(GlyphInfo);
-    nresults[2] = 0;
-    nresults[3] = (size_t)&(info->advanceY)-baseAddr;
-    nresults[4] = (size_t)&(info->width)-baseAddr;
-    nresults[5] = (size_t)&(info->height)-baseAddr;
-    nresults[6] = (size_t)&(info->rowBytes)-baseAddr;
-    nresults[7] = (size_t)&(info->topLeftX)-baseAddr;
-    nresults[8] = (size_t)&(info->topLeftY)-baseAddr;
-    nresults[9] = (size_t)&(info->image)-baseAddr;
-    nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */
-    nresults[11] = (size_t)&(info->cellInfo)-baseAddr;
-    nresults[12] = (size_t)&(info->managed)-baseAddr;
-
-    (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
+    GlyphInfo *info = (GlyphInfo*) calloc(1, sizeof(GlyphInfo));
+    return (jlong)(uintptr_t)info; /* invisible glyph */
 }
diff --git a/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java b/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java
index fff6919c464e9..cd090eab52ddd 100644
--- a/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java
+++ b/src/java.desktop/unix/classes/sun/font/XRGlyphCacheEntry.java
@@ -69,28 +69,25 @@ public int getGlyphSet() {
     }
 
     public static int getGlyphID(long glyphInfoPtr) {
-        // We need to access the GlyphID with Unsafe.getAddress() because the
+        // We need to access the GlyphID as a long because the
         // corresponding field in the underlying C data-structure is of type
         // 'void*' (see field 'cellInfo' of struct 'GlyphInfo'
         // in src/share/native/sun/font/fontscalerdefs.h).
         // On 64-bit Big-endian architectures it would be wrong to access this
-        // field with Unsafe.getInt().
-        return (int) StrikeCache.unsafe.getAddress(glyphInfoPtr +
-                                                   StrikeCache.cacheCellOffset);
+        // field as an int.
+        return (int)StrikeCache.getGlyphCellInfo(glyphInfoPtr);
     }
 
     public static void setGlyphID(long glyphInfoPtr, int id) {
-        // We need to access the GlyphID with Unsafe.putAddress() because the
+        // We need to access the GlyphID as a long because the
         // corresponding field in the underlying C data-structure is of type
-        // 'void*' (see field 'cellInfo' of struct 'GlyphInfo' in
-        // src/share/native/sun/font/fontscalerdefs.h).
-        // On 64-bit Big-endian architectures it would be wrong to write this
-        // field with Unsafe.putInt() because it is also accessed from native
-        // code as a 'long'.
+        // 'void*' (see field 'cellInfo' of struct 'GlyphInfo'
+        // in src/share/native/sun/font/fontscalerdefs.h).
+        // On 64-bit Big-endian architectures it would be wrong to access this
+        // field as an int
         // See Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative()
-        // in src/solaris/native/sun/java2d/x11/XRBackendNative.c
-        StrikeCache.unsafe.putAddress(glyphInfoPtr +
-                                      StrikeCache.cacheCellOffset, (long)id);
+        // in src/unix/native/sun/java2d/x11/XRBackendNative.c
+        StrikeCache.setGlyphCellInfo(glyphInfoPtr, (long)id);
     }
 
     public int getGlyphID() {
@@ -102,29 +99,27 @@ public void setGlyphID(int id) {
     }
 
     public float getXAdvance() {
-        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.xAdvanceOffset);
+        return StrikeCache.getGlyphXAdvance(glyphInfoPtr);
     }
 
     public float getYAdvance() {
-        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.yAdvanceOffset);
+        return StrikeCache.getGlyphYAdvance(glyphInfoPtr);
     }
 
     public int getSourceRowBytes() {
-        return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.rowBytesOffset);
+        return StrikeCache.getGlyphRowBytes(glyphInfoPtr);
     }
 
     public int getWidth() {
-        return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.widthOffset);
+        return StrikeCache.getGlyphWidth(glyphInfoPtr);
     }
 
     public int getHeight() {
-        return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.heightOffset);
+        return StrikeCache.getGlyphHeight(glyphInfoPtr);
     }
 
     public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) {
-        long pixelDataAddress =
-            StrikeCache.unsafe.getAddress(glyphInfoPtr +
-                                          StrikeCache.pixelDataOffset);
+        long pixelDataAddress = StrikeCache.getGlyphImagePtr(glyphInfoPtr);
         if (pixelDataAddress == 0L) {
             return;
         }
@@ -134,11 +129,12 @@ public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) {
         int rowBytes = getSourceRowBytes();
         int paddedWidth = getPaddedWidth(uploadAsLCD);
 
+        byte[] pixelBytes = StrikeCache.getGlyphPixelBytes(glyphInfoPtr);
         if (!uploadAsLCD) {
             for (int line = 0; line < height; line++) {
                 for(int x = 0; x < paddedWidth; x++) {
                     if(x < width) {
-                        os.write(StrikeCache.unsafe.getByte(pixelDataAddress + (line * rowBytes + x)));
+                        os.write(pixelBytes[(line * rowBytes + x)]);
                     }else {
                          /*pad to multiple of 4 bytes per line*/
                          os.write(0);
@@ -151,12 +147,9 @@ public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) {
                 int rowBytesWidth = width * 3;
                 int srcpix = 0;
                 while (srcpix < rowBytesWidth) {
-                    os.write(StrikeCache.unsafe.getByte
-                          (pixelDataAddress + (rowStart + srcpix + 2)));
-                    os.write(StrikeCache.unsafe.getByte
-                          (pixelDataAddress + (rowStart + srcpix + 1)));
-                    os.write(StrikeCache.unsafe.getByte
-                          (pixelDataAddress + (rowStart + srcpix + 0)));
+                    os.write(pixelBytes[rowStart + srcpix + 2]);
+                    os.write(pixelBytes[rowStart + srcpix + 1]);
+                    os.write(pixelBytes[rowStart + srcpix + 0]);
                     os.write(255);
                     srcpix += 3;
                 }
@@ -165,11 +158,11 @@ public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) {
     }
 
     public float getTopLeftXOffset() {
-        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftXOffset);
+        return StrikeCache.getGlyphTopLeftX(glyphInfoPtr);
     }
 
     public float getTopLeftYOffset() {
-        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftYOffset);
+        return StrikeCache.getGlyphTopLeftY(glyphInfoPtr);
     }
 
     public long getGlyphInfoPtr() {