import java.util.ArrayList;
import java.util.List;
class Demo {
}
public class Test {
public static void main(String[] args) {
List<Demo> demoList = new ArrayList<>();
while (true) {
demoList.add(new Demo());
}
}
}
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
,运行过程中计算机内存不断上升直到报错:-XX:+HeapDumpOnOutOfMemoryError -Xms20m -Xmx20m
来输出堆存储快照,在项目目录下出现名为 java_pid24672.hprof
的文件。如果想解析该文件,需要下载 Eclipse 提供的解析器 MemoryAnalyzer,下载地址:https://www.eclipse.org/mat/downloads.php,通过该软件打开 java_pid24672.hprof
文件可以看到内存的实际应用情况,判断内存溢出原因;C:\Program Files\Java\jdk1.8.0_171\bin
下,直接在命令行输入jconsole
即可运行,源代码在 tools.jar
包中;import java.util.ArrayList;
import java.util.List;
public class Test {
public byte[] b1 = new byte[128 * 1024];
public static void main(String[] args) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("start...");
fill(1000);
}
private static void fill(int n) {
List<Test> jlist = new ArrayList<>();
for(int i = 0;i < n;i++) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
jlist.add(new Test());
}
}
}
public class Test {
public static void main(String[] args) {
test();
}
public static void test() {
System.out.println("start......");
test();
}
}
public class Test {
public static void main(String[] args) {
// s1与s2是相等的,为字节码常亮
String s1 = "abc";
String s2 = "abc";
// s3创建在堆内存中
String s3 = new String("abc");
// intern方法可以将对象变为运行时常量
// intern是一个native方法
System.out.println(s1 == s3.intern()); // true
}
}
public class Test {
private Object instance;
public Test() {
// 占据20M内存
byte[] m = new byte[20 * 1024 * 1024];
}
public static void main(String[] args) {
Test c1 = new Test();
Test c2 = new Test();
c1.instance = c2;
c2.instance = c1;
// 断掉引用
c1 = null;
c2 = null;
//垃圾回收
System.gc();
}
}
-verbose:gc
;-verbose:gc -XX:+PrintGCDetails
;[GC (System.gc()) [PSYoungGen: 22476K->680K(38400K)] 42956K->21168K(125952K), 0.0008355 secs]
可以看出对象被回收,因此 Java 不使用引用计数算法;
很显然,整理这一下需要时间,所以与标记清除算法相比,这一步花费了不少时间,但从长远来看,这一步还是很有必要的;
-verbose:gc -XX:+PrintGCDetails
表示输出虚拟机中 GC 的详细情况;java -version
查看。也可以通过 -XX:+UseSerialGC
设置收集器;-Xms20M -Xmx20M -Xmn10M
设置内存大小大小为 20M,新生代大小为 10M;-XX:SurvivorRatio=8
设置 eden 与 survuvor 的比值大小 8:1;public class Test {
public static void main(String[] args) {
// -verbose:gc -XX:+PrintGCDetails -XX:+UseSerialGC -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8
byte[] b1 = new byte[2 * 1024 * 1024];
byte[] b2 = new byte[2 * 1024 * 1024];
byte[] b3 = new byte[2 * 1024 * 1024];
byte[] b4 = new byte[4 * 1024 * 1024]; //第一次Minor回收
System.gc();
}
}
[GC (Allocation Failure) [DefNew: 7291K->557K(9216K), 0.0051010 secs] 7291K->6701K(19456K), 0.0069568 secs] [Times: user=0.00 sys=0.02, real=0.01 secs]
[Full GC (System.gc()) [Tenured: 6144K->6144K(10240K), 0.0017958 secs] 10957K->10793K(19456K), [Metaspace: 2699K->2699K(1056768K)], 0.0020720 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4813K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 58% used [0x00000000fec00000, 0x00000000ff0b3708, 0x00000000ff400000)
from space 1024K, 0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
tenured generation total 10240K, used 6144K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 60% used [0x00000000ff600000, 0x00000000ffc00030, 0x00000000ffc00200, 0x0000000100000000)
Metaspace used 2705K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 297K, capacity 386K, committed 512K, reserved 1048576K
-XX:PretenureSizeThreshold=6M
设置大文件大小;public class Test {
public static void main(String[] args) {
byte[] b1 = new byte[7 * 1024 * 1024];
}
}
tenured generation total 10240K, used 7168K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 70% used [0x00000000ff600000, 0x00000000ffd00010, 0x00000000ffd00200, 0x0000000100000000)
-XX:MaxTenuringThreshold
最大年龄,默认为15;-XX:+HandlePromotionFailure
开启;-XX:-HandlePromotionFailure
禁用;public static StringBuffer craeteStringBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb;
}
jps -m
运行时传入主类的参数;jps -v
虚拟机参数;jps -l
运行的主类全名 或者 Jar 包名称;jsp -mlv
;jstat -gcutil 3344 1000 10
:每隔1000毫秒执行一次 10次;-XX:+HeapDumpOnOutOfMemoryError
相同的效果;jstack [option] vmid
;import java.util.Map;
public class Test {
public static void main(String[] args) {
Map<Thread, StackTraceElement[]> m = Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> en : m.entrySet()) {
Thread t = en.getKey();
StackTraceElement[] v = en.getValue();
System.out.println("Thread name is " + t.getName());
for (StackTraceElement s : v) {
System.out.println("\t" + s.toString());
}
}
}
}
import java.util.Scanner;
public class Test {
// 线程死循环演示
public static void createBusyThread() {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
;
}
}
}, "while_true").start();
}
// 线程锁等待演示
public static void createLockThread(final Object lock) {
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}, "wait").start();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
sc.next();
createBusyThread();
sc.next();
Object obj = new Object();
createLockThread(obj);
}
}
public class Test {
static class SynAddRunnable implements Runnable {
int a, b;
public SynAddRunnable(int a, int b) {
this.a = a;
this.b = b;
}
@Override
public void run() {
synchronized (Integer.valueOf(a)) {
synchronized (Integer.valueOf(b)) {
System.out.println(a + b);
}
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(new SynAddRunnable(1, 2)).start();
new Thread(new SynAddRunnable(2, 1)).start();
}
}
}
public class Test {
public static void main(String[] args) {
User user = new User();
User[] users = new User[10];
int[] is = new int[10];
user.name = "hello";
String username = user.name;
}
}
class User {
String name;
static int age;
}
Code:
stack=2, locals=5, args_size=1
0: new #2 // class User
3: dup
4: invokespecial #3 // Method User."<init>":()V
7: astore_1
8: bipush 10
10: anewarray #2 // class User
13: astore_2
14: bipush 10
16: newarray int
18: astore_3
19: aload_1
20: ldc #4 // String hello
22: putfield #5 // Field User.name:Ljava/lang/String;
25: aload_1
26: getfield #5 // Field User.name:Ljava/lang/String;
29: astore 4
31: return
public class Test {
public static void main(String[] args) {
int a = 10;
if (a > 10) {
System.out.println(">10");
} else {
System.out.println(">=10");
}
}
}
Code:
stack=2, locals=2, args_size=1
0: bipush 10
2: istore_1
3: iload_1
4: bipush 10
6: if_icmple 20
9: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
12: ldc #3 // String >10
14: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: goto 28
20: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
23: ldc #5 // String >=10
25: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
public class Test {
public static void main(String[] args) {
int a = 0;
throw new RuntimeException("Exception......");
}
}
Code:
stack=3, locals=2, args_size=1
0: iconst_0
1: istore_1
2: new #2 // class java/lang/RuntimeException
5: dup
6: ldc #3 // String Exception......
8: invokespecial #4 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
11: athrow
class Parent {
static {
System.out.println("父类加载...");
}
}
class Child extends Parent {
static {
System.out.println("子类加载...");
}
}
public class Test {
public static void main(String[] args) {
System.out.println("子类运行...");
}
}
/* 运行结果: 父类加载... 子类加载... 子类运行... */
class SuperClass {
static {
System.out.println("SuperClass(父类)被初始化了。。。");
}
public static int value = 66;
}
class Subclass extends SuperClass {
static {
System.out.println("Subclass(子类)被初始化了。。。");
}
}
public class Test {
public static void main(String[] args) {
// 1:通过子类调用父类的静态字段不会导致子类初始化
// System.out.println(Subclass.value);//SuperClass(父类)被初始化了。。。
// 2:通过数组定义引用类,不会触发此类的初始化
SuperClass[] superClasses = new SuperClass[3];
// 3:通过new 创建对象,可以实现类初始化,必须把1下面的代码注释掉才有效果不然经过1的时候类已经初始化了,下面这条语句也就没用了。
//SuperClass superClass = new SuperClass();
}
}
加载过程:
public class Test {
static {
i = 0; //给变量赋值可以正常编译
System.out.println(i); //编译器提示:“非法向前引用”
}
static int i = 1;
}
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
//1 首先检查类是否被加载
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
//2 没有则调用父类加载器的loadClass()方法;
c = parent.loadClass(name, false);
} else {
//3 若父类加载器为空,则默认使用启动类加载器作为父加载器;
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
//4 若父类加载失败,抛出ClassNotFoundException 异常后
c = findClass(name);
}
}
if (resolve) {
//5 再调用自己的findClass() 方法。
resolveClass(c);
}
return c;
}
原文链接:https://blog.csdn.net/TJtulong/article/details/89598598