-
Notifications
You must be signed in to change notification settings - Fork 333
Expand file tree
/
Copy pathUnsafeUtils.java
More file actions
72 lines (62 loc) · 2.03 KB
/
UnsafeUtils.java
File metadata and controls
72 lines (62 loc) · 2.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package datadog.trace.util;
import de.thetaphi.forbiddenapis.SuppressForbidden;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.Unsafe;
public abstract class UnsafeUtils {
private static final Logger log = LoggerFactory.getLogger(UnsafeUtils.class);
private static final Unsafe UNSAFE = getUnsafe();
private static Unsafe getUnsafe() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
} catch (Throwable t) {
log.debug("Unsafe is unavailable", t);
return null;
}
}
/**
* Tries to create a shallow clone of the provided object: another instance of the same class
* whose fields have the same values as the original (for reference fields that means referring to
* the same objects).
*
* <p>If cloning fails, the original instance is returned.
*
* @param original Original object
* @return A shallow clone
* @param <T> Type of the object being cloned
*/
@SuppressWarnings("unchecked")
public static <T> T tryShallowClone(T original) {
if (UNSAFE == null) {
log.debug("Unsafe is unavailable, {} will not be cloned", original);
return original;
}
try {
Class<?> clazz = original.getClass();
T clone = (T) UNSAFE.allocateInstance(clazz);
while (clazz != Object.class) {
cloneFields(clazz, original, clone);
clazz = clazz.getSuperclass();
}
return clone;
} catch (Throwable t) {
log.debug("Error while cloning {}: {}", original, t);
return original;
}
}
@SuppressForbidden
private static void cloneFields(Class<?> clazz, Object original, Object clone) throws Exception {
for (Field field : clazz.getDeclaredFields()) {
if ((field.getModifiers() & Modifier.STATIC) != 0) {
continue;
}
field.setAccessible(true);
Object fieldValue = field.get(original);
field.set(clone, fieldValue);
}
}
}