97

I have a byte[] and would like to copy it into another byte[]. Maybe I am showing my simple 'C' background here, but is there an equivalent to memcpy() on byte arrays in Java?

simon
  • 5,777
  • 7
  • 30
  • 36

9 Answers9

120

Use System.arraycopy()

System.arraycopy(sourceArray, 
                 sourceStartIndex,
                 targetArray,
                 targetStartIndex,
                 length);

Example,

String[] source = { "alpha", "beta", "gamma" };
String[] target = new String[source.length];
System.arraycopy(source, 0, target, 0, source.length);


or use Arrays.copyOf()
Example,

target = Arrays.copyOf(source, length);

java.util.Arrays.copyOf(byte[] source, int length) was added in JDK 1.6.

The copyOf() method uses System.arrayCopy() to make a copy of the array, but is more flexible than clone() since you can make copies of parts of an array.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Zaki
  • 6,997
  • 6
  • 37
  • 53
  • 6
    Arrays.copyOf() also allocates memory. in your example if you change String[] target = new String[4]; and then target = Arrays.copyOf() it creates a new target which is a String[3]. Not the memcopy behavior. – MikeF Jun 14 '16 at 13:11
  • Arrays.copyOf internally uses System.arraycopy which is a native method. – Gajraj Tanwar Nov 27 '19 at 06:52
90

You might try System.arraycopy or make use of array functions in the Arrays class like java.util.Arrays.copyOf. Both should give you native performance under the hood.

Arrays.copyOf is probably favourable for readability, but was only introduced in java 1.6.

 byte[] src = {1, 2, 3, 4};
 byte[] dst = Arrays.copyOf(src, src.length);
 System.out.println(Arrays.toString(dst));
Tom
  • 4,742
  • 25
  • 32
  • 1
    I think the second option is more "logical". I never understood why System.arraycopy() is where is, one of the clumsiest possible locations. – sinuhepop Jul 25 '10 at 13:29
  • @Sinuhe - it is there for historical reasons. – Stephen C Jul 25 '10 at 13:46
  • 33
    This is NOT the correct answer. memcpy() does not allocate data, only copies to an existing buffer. While Arrays.copyOf() clearly allocate new memory. – splinux Feb 17 '16 at 17:10
12

If you just want an exact copy of a one-dimensional array, use clone().

byte[] array = { 0x0A, 0x01 };
byte[] copy = array.clone();

For other array copy operations, use System.arrayCopy/Arrays.copyOf as Tom suggests.

In general, clone should be avoided, but this is an exception to the rule.

Community
  • 1
  • 1
McDowell
  • 107,573
  • 31
  • 204
  • 267
  • See also more detail in the accepted answer to http://stackoverflow.com/questions/3208899/how-do-i-clone-a-java-byte-array . – Andy Thomas Jan 08 '15 at 17:04
5

You can use System.arrayCopy. It copies elements from a source array to a destination array. The Sun implementation uses hand-optimized assembler, so this is fast.

mdma
  • 56,943
  • 12
  • 94
  • 128
4

Java actually does have something just like memcpy(). The Unsafe class has a copyMemory() method that is essentially identical to memcpy(). Of course, like memcpy(), it provides no protection from memory overlays, data destruction, etc. It is not clear if it is really a memcpy() or a memmove(). It can be used to copy from actual addresses to actual addresses or from references to references. Note that if references are used, you must provide an offset (or the JVM will die ASAP).

Unsafe.copyMemory() works (up to 2 GB per second on my old tired PC). Use at your own risk. Note that the Unsafe class does not exist for all JVM implementations.

Peter Schaeffer
  • 371
  • 4
  • 9
  • sorry for going all pet sematary on this ancient thread, but could you given me an example on how to do that with an array of references. And is it faster for small amounts of data (like 1-4 MB) or just worthy in case of larger data like the 2GB you mentioned? – FinnTheHuman Jun 29 '16 at 16:16
  • 2
    Using the `sun.misc.Unsafe` class is considered a bad practice "hack" b/c it's a *private* package class. In addition, starting in Java 9, it won't be available anymore, so trying to use this class is the same as begging for your code to break unexpectedly. – code_dredd May 30 '17 at 07:45
2

You can use System.arraycopy

Artem Barger
  • 40,769
  • 9
  • 59
  • 81
2

When you are using JDK 1.5+ You should use

System.arraycopy()

Instead of

Arrays.copyOfRange()

Beacuse Arrays.copyOfRange() wasn't added until JDK 1.6.So you might get

Java - “Cannot Find Symbol” error

when calling Arrays.copyOfRange in that version of JDK.

0

Use byteBufferViewVarHandle or byteArrayViewVarHandle.

This will let you copy an array of "longs" directly to an array of "doubles" and similar with something like:

public long[] toLongs(byte[] buf) {
    int end = buf.length >> 3;
    long[] newArray = new long[end];
    for (int ii = 0; ii < end; ++ii) {
        newArray[ii] = (long)AS_LONGS_VH.get(buf, ALIGN_OFFSET + ii << 3);
    }
}

private static final ALIGN_OFFSET = ByteBuffer.wrap(new byte[0]).alignmentOffset(8); 
private static final VarHandle AS_LONGS_VH = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.nativeOrder());

This will let you do the bit hacking like:

float thefloat = 0.4;
int floatBits;
_Static_assert(sizeof theFloat == sizeof floatBits, "this bit twiddling hack requires floats to be equal in size to ints");
memcpy(&floatBits, &thefloat, sizeof floatBits);
0

No. Java does not have an equivalent to memcpy. Java has an equivalent to memmove instead.

If the src and dest arguments refer to the same array object, then the copying is performed as if the components at positions srcPos through srcPos+length-1 were first copied to a temporary array with length components and then the contents of the temporary array were copied into positions destPos through destPos+length-1 of the destination array.

Oracle Docs

It is very likely System.arraycopy will never have the same performance as memcpy if src and dest refer to the same array. Usually this will be fast enough though.