/*
 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
 * 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * The contents of this file are subject to the terms of either the Universal Permissive License
 * v 1.0 as shown at http://oss.oracle.com/licenses/upl
 *
 * or the following license:
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions
 * and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
 * conditions and the following disclaimer in the documentation and/or other materials provided with
 * the distribution.
 * 
 * 3. Neither the name of the copyright holder nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package examples;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A simple piece of code that generates a bunch of problematic data structures and then goes into
 * sleep for long enough for the user to take a heap dump. The resulting dump is stored alongside
 * the test source files and is analyzed in org.openjdk.jmc.joverflow.stats.CodeAnalyzerTest.
 * <p>
 * Memory problems demonstrated in this class are those that can be detected by code analysis in
 * JOverflow.
 * <p>
 * IMPORTANT: a heap dump for this class should be generated by the JVM running in 32-bit mode.
 * Numbers in the test are based on pointer size etc. in this mode, where we know their exact values
 * and don't have to care about different object header size on different VMs, compressed
 * references, etc.
 */
@SuppressWarnings("unused")
public class FixableIssues {

	public static final int NUM_DEAD_FIELD_HOLDERS = 20000;
	public static final int NUM_SMALL_SPARSE_MAP_HOLDERS = 10000;
	public static final int NUM_EMPTY_LIST_HOLDERS = 10000;

	/** This class contains private fields that are never written */
	public static class DeadFieldHolder {
		private Object dataField; // This field is never written

		public Object getDataField() {
			return dataField;
		}
	}

	/**
	 * This class contains collections that are small and sparse, and could be fixed if created with
	 * appropriate initial size.
	 */
	public static class SmallSparseMapHolder {
		private Map<String, Integer> map;

		public SmallSparseMapHolder(int i) {
			map = new HashMap<>();
			map.put(Integer.toString(i), i);
		}

		public int getValueForString(String s) {
			return map.get(s);
		}
	}

	public static class EmptyListHolder {
		private List<String> list;

		public EmptyListHolder(String[] ar) {
			list = new ArrayList<>();
			if (ar.length > 0) {
				for (int i = 0; i < ar.length; i++) {
					list.add(ar[i]);
				}
			}
		}

		public String getValue(int idx) {
			return list.get(idx);
		}
	}

	public Object deadFieldHolders[];
	public Object smallSparseMapHolders[];
	public Object emptyListHolders[];

	/** Main method that initializes all data and goes into sleep */
	public static void main(String args[]) {
		FixableIssues f = new FixableIssues();

		ExampleUtils.printPidAndSleep("fixable-issues.hprof");
	}

	public FixableIssues() {
		deadFieldHolders = new Object[NUM_DEAD_FIELD_HOLDERS];
		for (int i = 0; i < NUM_DEAD_FIELD_HOLDERS; i++) {
			deadFieldHolders[i] = new DeadFieldHolder();
		}

		smallSparseMapHolders = new Object[NUM_SMALL_SPARSE_MAP_HOLDERS];
		for (int i = 0; i < NUM_SMALL_SPARSE_MAP_HOLDERS; i++) {
			smallSparseMapHolders[i] = new SmallSparseMapHolder(i);
		}

		String emptyStringArray[] = new String[0];
		emptyListHolders = new Object[NUM_EMPTY_LIST_HOLDERS];
		for (int i = 0; i < NUM_EMPTY_LIST_HOLDERS; i++) {
			emptyListHolders[i] = new EmptyListHolder(emptyStringArray);
		}
	}
}
