diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp index dd4c3db3f3c2efcbcbc3a3cbb89c56b4a0a4b9c1..b535365684392045433cac4e0b4a1938ceb140cd 100644 --- a/src/share/vm/gc_interface/collectedHeap.hpp +++ b/src/share/vm/gc_interface/collectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -319,7 +319,10 @@ class CollectedHeap : public CHeapObj { inline static oop obj_allocate(KlassHandle klass, int size, TRAPS); inline static oop array_allocate(KlassHandle klass, int size, int length, TRAPS); inline static oop array_allocate_nozero(KlassHandle klass, int size, int length, TRAPS); + private: + inline static void check_array_size(int size, int length, TRAPS); + public: inline static void post_allocation_install_obj_klass(KlassHandle klass, oop obj); diff --git a/src/share/vm/gc_interface/collectedHeap.inline.hpp b/src/share/vm/gc_interface/collectedHeap.inline.hpp index 89bfc5b9aa2b49555e7df71700e83ce69c0b000f..39ff0616447b1f28f4c59a820a8835303a95c184 100644 --- a/src/share/vm/gc_interface/collectedHeap.inline.hpp +++ b/src/share/vm/gc_interface/collectedHeap.inline.hpp @@ -206,6 +206,30 @@ oop CollectedHeap::obj_allocate(KlassHandle klass, int size, TRAPS) { return (oop)obj; } +void CollectedHeap::check_array_size(int size, + int length, + TRAPS) { + if (size >= ArrayAllocationWarningSize >> LogHeapWordSize) { + //JavaThread::name() may need allocation + ResourceMark rm(THREAD); + //give a warning + tty->print_cr("==WARNING== allocating large array--" \ + "thread_id[" INTPTR_FORMAT "]--" \ + "thread_name[%s]--" \ + "array_size[" SIZE_FORMAT " bytes]--" \ + "array_length[%d elememts]", + p2i(THREAD), THREAD->name(), + (size_t)size * HeapWordSize, length); + + //print stack info + THREAD->print_on(tty); + tty->cr(); + if (THREAD->is_Java_thread()) { + ((JavaThread*) THREAD)->print_stack_on(tty); + } + } +} + oop CollectedHeap::array_allocate(KlassHandle klass, int size, int length, @@ -213,6 +237,7 @@ oop CollectedHeap::array_allocate(KlassHandle klass, debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); + check_array_size(size, length, THREAD); HeapWord* obj = common_mem_allocate_init(klass, size, CHECK_NULL); post_allocation_setup_array(klass, obj, length); NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size)); @@ -226,6 +251,7 @@ oop CollectedHeap::array_allocate_nozero(KlassHandle klass, debug_only(check_for_valid_allocation_state()); assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed"); assert(size >= 0, "int won't convert to size_t"); + check_array_size(size, length, THREAD); HeapWord* obj = common_mem_allocate_noinit(klass, size, CHECK_NULL); ((oop)obj)->set_klass_gap(0); post_allocation_setup_array(klass, obj, length); diff --git a/src/share/vm/runtime/globals_ext.hpp b/src/share/vm/runtime/globals_ext.hpp index 733be2d82803c6d5c737cbfe6ddb1a094afcebbe..aabe2a67c4c544c337d8701a919ea1a4bac8b03a 100644 --- a/src/share/vm/runtime/globals_ext.hpp +++ b/src/share/vm/runtime/globals_ext.hpp @@ -33,7 +33,11 @@ \ manageable(bool, PrintGCRootsTraceTime, false, \ "Print GC Trace Time") \ - + \ + manageable(intx, ArrayAllocationWarningSize, 512*M, \ + "Desired size of array space allocation before " \ + "printing a warning") \ + \ //add new AJVM specific flags here diff --git a/test/runtime/memory/TestArrayAllocationWarning.java b/test/runtime/memory/TestArrayAllocationWarning.java new file mode 100644 index 0000000000000000000000000000000000000000..11ac08eb0897547738efd8b6986f9c641390a728 --- /dev/null +++ b/test/runtime/memory/TestArrayAllocationWarning.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019 Alibaba Group Holding Limited. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Alibaba designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + + +import com.oracle.java.testlibrary.*; +import static com.oracle.java.testlibrary.Asserts.*; +import java.lang.management.ManagementFactory; +import com.sun.management.HotSpotDiagnosticMXBean; + +/* + * @test + * @summary Test large array allocation warning "-XX:ArrayAllocationWarningSize=4M" + * @library /testlibrary + * @build TestArrayAllocationWarning + * @run main TestArrayAllocationWarning + */ +public class TestArrayAllocationWarning { + public static void main(String[] args) throws Exception { + ProcessBuilder pb; + OutputAnalyzer output; + String srcPath = System.getProperty("test.class.path"); + + pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:.", + "-cp", ".:" + srcPath, + TestArrayAllocationWarningRunner.class.getName()); + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("==WARNING== allocating large array--"); + output.shouldContain("done!"); + output.shouldHaveExitValue(0); + System.out.println(output.getOutput()); + + pb = ProcessTools.createJavaProcessBuilder("-Xbootclasspath/a:.", + "-cp", ".:" + srcPath, + TestArrayAllocationWarningRunner.class.getName(), + "ArrayAllocationWarningSize", + "4M"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("==WARNING== allocating large array--"); + output.shouldContain("done!"); + output.shouldHaveExitValue(0); + System.out.println(output.getOutput()); + } + + public static class TestArrayAllocationWarningRunner { + public static void allocateArray(int size) { + Object[] array = new Object[size]; + // avoid optimized out + System.out.println(array); + } + public static void main(String[] args) throws Exception { + if (args.length == 0) { + allocateArray(8 * 1000 * 1000); + } else { + assertTrue(args.length == 2); + String key = args[0]; + String value = args[1].replace("M", "000000"); + System.out.println(key); + System.out.println(value); + HotSpotDiagnosticMXBean bean = (HotSpotDiagnosticMXBean) + ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); + System.out.println(bean.getVMOption(key).getValue()); + bean.setVMOption(key, value); + allocateArray(8 * 1000 * 1000); + } + System.out.println("done!"); + } + } +} +