Skip to content

java unsafe

Posted on:March 29, 2023 at 07:46 PM

背景

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;
}

相关阅读