背景
java的unsafe包是有很多底层的api暴露出来,举例,java的netty就大量使用这个api
例子
下面是java的unsafe包里面的allocateMemory
方法.
public class UnsafeDemo {
public static void main(String[] args) {
var unsafe = getUnsafe();
var memory = unsafe.allocateMemory(100);
System.out.println(memory);
}
private static Unsafe getUnsafe() {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
return null;
}
}
}
这里memory 返回的是一个地址
实际上是调用Unsafe_AllocateMemory0
UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) {
size_t sz = (size_t)size;
assert(is_aligned(sz, HeapWordSize), "sz not aligned");
void* x = os::malloc(sz, mtOther);
return addr_to_java(x);
} UNSAFE_END
最后调用的是glibc 的malloc
void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
// Special handling for NMT preinit phase before arguments are parsed
void* rc = NULL;
if (NMTPreInit::handle_malloc(&rc, size)) {
// No need to fill with 0 because DumpSharedSpaces doesn't use these
// early allocations.
return rc;
}
DEBUG_ONLY(check_crash_protection());
// On malloc(0), implementations of malloc(3) have the choice to return either
// NULL or a unique non-NULL pointer. To unify libc behavior across our platforms
// we chose the latter.
size = MAX2((size_t)1, size);
// For the test flag -XX:MallocMaxTestWords
if (has_reached_max_malloc_test_peak(size)) {
return NULL;
}
const size_t outer_size = size + MemTracker::overhead_per_malloc();
// Check for overflow.
if (outer_size < size) {
return NULL;
}
ALLOW_C_FUNCTION(::malloc, void* const outer_ptr = ::malloc(outer_size);) <-- malloc 分配内存
if (outer_ptr == NULL) {
return NULL;
}
void* const inner_ptr = MemTracker::record_malloc((address)outer_ptr, size, memflags, stack);
if (DumpSharedSpaces) {
// Need to deterministically fill all the alignment gaps in C++ structures.
::memset(inner_ptr, 0, size);
} else {
DEBUG_ONLY(::memset(inner_ptr, uninitBlockPad, size);)
}
DEBUG_ONLY(break_if_ptr_caught(inner_ptr);)
return inner_ptr;
}