001/* 002 * Copyright 2013 Alex Kasko (alexkasko.com) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.alexkasko.unsafe.bytearray; 018 019import sun.misc.Unsafe; 020 021import java.lang.reflect.Field; 022 023/** 024 * Implementation of {@link ByteArrayTool} using {@code sun.misc.Unsafe}. 025 * All bound checks are done using {@code assert} keyword, they may be enabled 026 * with java {@code ea} switch. 027 * 028 * @author alexkasko 029 * Date: 12/11/12 030 */ 031class UnsafeByteArrayTool extends ByteArrayTool { 032 033 private static final Unsafe UNSAFE; 034 private static final long BYTE_ARRAY_OFFSET; 035 036 static { 037 try { 038 Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 039 theUnsafe.setAccessible(true); 040 UNSAFE = (Unsafe) theUnsafe.get(null); 041 int boo = UNSAFE.arrayBaseOffset(byte[].class); 042 // It seems not all Unsafe implementations implement the following method. 043 UNSAFE.copyMemory(new byte[1], boo, new byte[1], boo, 1); 044 BYTE_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(byte[].class); 045 } catch (Exception e) { 046 throw new RuntimeException(e); 047 } 048 } 049 050 /** 051 * {@inheritDoc} 052 */ 053 @Override 054 public boolean isUnsafe() { 055 return true; 056 } 057 058 /** 059 * {@inheritDoc} 060 */ 061 @Override 062 public byte getByte(byte[] data, int offset) { 063 assert offset >= 0 : offset; 064 assert offset <= data.length - 1 : offset; 065 return UNSAFE.getByte(data, BYTE_ARRAY_OFFSET + offset); 066 } 067 068 /** 069 * {@inheritDoc} 070 */ 071 @Override 072 public void putByte(byte[] data, int offset, byte value) { 073 assert offset >= 0 : offset; 074 assert offset <= data.length - 1 : offset; 075 UNSAFE.putByte(data, BYTE_ARRAY_OFFSET + offset, value); 076 } 077 078 /** 079 * {@inheritDoc} 080 */ 081 @Override 082 public short getUnsignedByte(byte[] data, int offset) { 083 assert offset >= 0 : offset; 084 assert offset <= data.length - 1 : offset; 085 return (short) (UNSAFE.getByte(data, BYTE_ARRAY_OFFSET + offset) & 0xff); 086 } 087 088 /** 089 * {@inheritDoc} 090 */ 091 @Override 092 public void putUnsignedByte(byte[] data, int offset, short value) { 093 assert offset >= 0 : offset; 094 assert offset <= data.length - 1 : offset; 095 assert value >= 0 : value; 096 assert value < 1<<8 : value; 097 UNSAFE.putByte(data, BYTE_ARRAY_OFFSET + offset, (byte) value); 098 } 099 100 /** 101 * {@inheritDoc} 102 */ 103 @Override 104 public short getShort(byte[] data, int offset) { 105 assert offset >= 0 : offset; 106 assert offset <= data.length - 2 : offset; 107 return UNSAFE.getShort(data, BYTE_ARRAY_OFFSET + offset); 108 } 109 110 /** 111 * {@inheritDoc} 112 */ 113 @Override 114 public void putShort(byte[] data, int offset, short value) { 115 assert offset >= 0 : offset; 116 assert offset <= data.length - 2 : offset; 117 UNSAFE.putShort(data, BYTE_ARRAY_OFFSET + offset, value); 118 } 119 120 /** 121 * {@inheritDoc} 122 */ 123 @Override 124 public int getUnsignedShort(byte[] data, int offset) { 125 assert offset >= 0 : offset; 126 assert offset <= data.length - 2 : offset; 127 return UNSAFE.getShort(data, BYTE_ARRAY_OFFSET + offset) & 0xffff; 128 129 } 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public void putUnsignedShort(byte[] data, int offset, int value) { 136 assert offset >= 0 : offset; 137 assert offset <= data.length - 2 : offset; 138 assert value >= 0 : value; 139 assert value < 1<<16 : value; 140 UNSAFE.putShort(data, BYTE_ARRAY_OFFSET + offset, (short) value); 141 } 142 143 /** 144 * {@inheritDoc} 145 */ 146 @Override 147 public int getInt(byte[] data, int offset) { 148 assert offset >= 0 : offset; 149 assert offset <= data.length - 4 : offset; 150 return UNSAFE.getInt(data, BYTE_ARRAY_OFFSET + offset); 151 } 152 153 /** 154 * {@inheritDoc} 155 */ 156 @Override 157 public void putInt(byte[] data, int offset, int value) { 158 assert offset >= 0 : offset; 159 assert offset <= data.length - 4 : offset; 160 UNSAFE.putInt(data, BYTE_ARRAY_OFFSET + offset, value); 161 } 162 163 /** 164 * {@inheritDoc} 165 */ 166 @Override 167 public long getUnsignedInt(byte[] data, int offset) { 168 assert offset >= 0 : offset; 169 assert offset <= data.length - 4 : offset; 170 return UNSAFE.getInt(data, BYTE_ARRAY_OFFSET + offset) & 0xffffffffL; 171 } 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override 177 public void putUnsignedInt(byte[] data, int offset, long value) { 178 assert offset >= 0 : offset; 179 assert offset <= data.length - 4 : offset; 180 assert value >= 0 : value; 181 assert value < 1L<<32 : value; 182 UNSAFE.putInt(data, BYTE_ARRAY_OFFSET + offset, (int) value); 183 } 184 185 /** 186 * {@inheritDoc} 187 */ 188 @Override 189 public long getLong(byte[] data, int offset) { 190 assert offset >= 0 : offset; 191 assert offset <= data.length - 8 : offset; 192 return UNSAFE.getLong(data, BYTE_ARRAY_OFFSET + offset); 193 } 194 195 /** 196 * {@inheritDoc} 197 */ 198 @Override 199 public void putLong(byte[] data, int offset, long value) { 200 assert offset >= 0 : offset; 201 assert offset <= data.length - 8 : offset; 202 UNSAFE.putLong(data, BYTE_ARRAY_OFFSET + offset, value); 203 } 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override 209 public void copy(byte[] src, int srcPos, byte[] dest, int destPos, int length) { 210 assert srcPos >= 0 : srcPos; 211 assert srcPos <= src.length - length : srcPos; 212 assert destPos >= 0 : destPos; 213 assert destPos <= dest.length - length : destPos; 214 UNSAFE.copyMemory(src, BYTE_ARRAY_OFFSET + srcPos, dest, BYTE_ARRAY_OFFSET + destPos, length); 215 } 216}