2016-01-14 15:35:21 +03:00
/ *
2016-02-08 14:50:54 +03:00
* Copyright ( c ) 2015 , 2016 , Oracle and / or its affiliates . All rights reserved .
2016-01-14 15:35:21 +03:00
* 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 .
*
* 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 .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
* /
package utils ;
import java.lang.management.ManagementFactory ;
import java.lang.management.MemoryPoolMXBean ;
import java.lang.management.MemoryUsage ;
import java.util.ArrayList ;
import java.util.List ;
/ * *
*
* Utilities to provoke GC in various ways
* /
public class GcProvokerImpl implements GcProvoker {
private static List < Object > eatenMetaspace ;
private static List < Object > eatenMemory ;
static List < Object > eatHeapMemory ( float targetUsage ) {
long maxMemory = Runtime . getRuntime ( ) . maxMemory ( ) ;
// uses fixed small objects to avoid Humongous objects allocation in G1
int memoryChunk = 2048 ;
List < Object > list = new ArrayList < > ( ) ;
2016-06-15 09:43:42 +02:00
long used = 0 ;
long target = ( long ) ( maxMemory * targetUsage ) ;
while ( used < target ) {
2016-01-14 15:35:21 +03:00
try {
list . add ( new byte [ memoryChunk ] ) ;
used + = memoryChunk ;
} catch ( OutOfMemoryError e ) {
list = null ;
2016-10-19 10:10:51 +03:00
throw new RuntimeException ( " Unexpected OOME ' " + e . getMessage ( ) + " ' while eating " + targetUsage + " of heap memory. " ) ;
2016-01-14 15:35:21 +03:00
}
}
return list ;
}
@Override
public void provokeGc ( ) {
for ( int i = 0 ; i < 3 ; i + + ) {
long edenSize = Pools . getEdenCommittedSize ( ) ;
long heapSize = Pools . getHeapCommittedSize ( ) ;
float targetPercent = ( ( float ) edenSize ) / ( heapSize ) ;
2016-02-08 14:50:54 +03:00
if ( ( targetPercent < 0 ) | | ( targetPercent > 1 . 0 ) ) {
2016-01-14 15:35:21 +03:00
throw new RuntimeException ( " Error in the percent calculation " + " (eden size: " + edenSize + " , heap size: " + heapSize + " , calculated eden percent: " + targetPercent + " ) " ) ;
}
eatHeapMemory ( targetPercent ) ;
eatHeapMemory ( targetPercent ) ;
System . gc ( ) ;
}
}
@Override
public void eatMetaspaceAndHeap ( float targetMemoryUsagePercent ) {
2016-10-19 10:10:51 +03:00
// Metaspace should be filled before Java Heap to prevent unexpected OOME
// in the Java Heap while filling Metaspace
2016-01-14 15:35:21 +03:00
eatenMetaspace = eatMetaspace ( targetMemoryUsagePercent ) ;
2016-10-19 10:10:51 +03:00
eatenMemory = eatHeapMemory ( targetMemoryUsagePercent ) ;
2016-01-14 15:35:21 +03:00
}
private static List < Object > eatMetaspace ( float targetUsage ) {
List < Object > list = new ArrayList < > ( ) ;
final String metaspacePoolName = " Metaspace " ;
MemoryPoolMXBean metaspacePool = null ;
for ( MemoryPoolMXBean pool : ManagementFactory . getMemoryPoolMXBeans ( ) ) {
if ( pool . getName ( ) . contains ( metaspacePoolName ) ) {
metaspacePool = pool ;
break ;
}
}
if ( metaspacePool = = null ) {
throw new RuntimeException ( " MXBean for Metaspace pool wasn't found " ) ;
}
float currentUsage ;
GeneratedClassProducer gp = new GeneratedClassProducer ( ) ;
do {
try {
list . add ( gp . create ( 0 ) ) ;
} catch ( OutOfMemoryError oome ) {
list = null ;
2016-10-19 10:10:51 +03:00
throw new RuntimeException ( " Unexpected OOME ' " + oome . getMessage ( ) + " ' while eating " + targetUsage + " of Metaspace. " ) ;
2016-01-14 15:35:21 +03:00
}
MemoryUsage memoryUsage = metaspacePool . getUsage ( ) ;
currentUsage = ( ( ( float ) memoryUsage . getUsed ( ) ) / memoryUsage . getMax ( ) ) ;
} while ( currentUsage < targetUsage ) ;
return list ;
}
public GcProvokerImpl ( ) {
}
}