反编译:
可以获取该类的所有的方法,但是不能获取继承的或者所实现的接口的方法。
只能获取该类的public方法,但是能够获取继承的public方法和所实现的接口的方法。
自定义classLoader
package com.interview.javabasic.reflect;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class MyClassLoader extends ClassLoader {
private String path;
private String classLoaderName;
public MyClassLoader(String path, String classLoaderName) {
this.path = path;
this.classLoaderName = classLoaderName;
}
//用于寻找类文件
@Override
public Class findClass(String name) {
byte[] b = loadClassData(name);
return defineClass(name, b, 0, b.length);
}
//用于加载类文件
private byte[] loadClassData(String name) {
name = path + name + ".class";
InputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(new File(name));
out = new ByteArrayOutputStream();
int i = 0;
while ((i = in.read()) != -1) {
out.write(i);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return out.toByteArray();
}
}
package com.interview.javabasic.reflect;
public class ClassLoaderChecker {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
MyClassLoader m = new MyClassLoader("/Users/baidu/Desktop/", "myClassLoader");
Class c = m.loadClass("Wali");
System.out.println(c.getClassLoader());
System.out.println(c.getClassLoader().getParent());
System.out.println(c.getClassLoader().getParent().getParent());
System.out.println(c.getClassLoader().getParent().getParent().getParent());
c.newInstance();
}
}
package com.interview.javabasic.reflect;
public class ClassLoaderChecker {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
MyClassLoader m = new MyClassLoader("/Users/baidu/Desktop/", "myClassLoader");
Class c = m.loadClass("Wali");
System.out.println(c.getClassLoader());
System.out.println(c.getClassLoader().getParent());
System.out.println(c.getClassLoader().getParent().getParent());
System.out.println(c.getClassLoader().getParent().getParent().getParent());
c.newInstance();
}
}
package com.interview.javabasic.reflect;
public class Robot {
private String name;
public void sayHi(String helloSentence){
System.out.println(helloSentence + " " + name);
}
private String throwHello(String tag){
return "Hello " + tag;
}
static {
System.out.println("Hello Robot");
}
}
package com.interview.javabasic.reflect;
public class LoadDifference {
public static void main(String[] args) throws ClassNotFoundException {
//ClassLoader cl = Robot.class.getClassLoader();//无反应
//Class r = Class.forName("com.interview.javabasic.reflect.Robot");//输出静态语句,证明执行了初始化该类
}
}
package com.interview.javabasic.reflect;
加载数据库驱动的类:
public class LoadDifference {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
}
}
loadClass:
Spring ioc加载xml配置文件中的bean,使用懒加载加快初始化速度,loadClass不需要执行验证和链接的步骤。
反编译:
Istore弹出栈,iload压入栈。
全是正数时:
package com.interview.javabasic.jvm.model;
public class Fibonacci {
//F(0)=0,F(1)=1,当n>=2的时候,F(n) = F(n-1) + F(n-2),
//F(2)=F(1) + F(0) = 1, F(3) = F(2) + F(1) = 1+1 = 2
//F(0)-F(N) 依次为 0,1,1,2,3,5,8,13,21,34...
public static int fibonacci(int n){
if(n == 0) {return 0;}
if(n == 1) {return 1;}
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String[] args) {
System.out.println(fibonacci(1000000));
}
}
一般讲-Xms和-Xmx设置为一样的值,防止内存扩充时内存抖动。
package com.interview.javabasic.jvm.model;
import java.util.Random;
public class PermGenErrTest {
public static void main(String[] args) {
for(int i=0; i <= 1000; i++){
//将返回的随机字符串添加到字符串常量池中
getRandomString(1000000).intern();
}
System.out.println("Mission Complete!");
}
//返回指定长度的随机字符串
private static String getRandomString(int length) {
//字符串源
String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for ( int i = 0; i < length; i++){
int number = random.nextInt(62);
sb.append(str.charAt(number));
}
return sb.toString();
}
}
Jdk6:
永久代大小:
Jdk7:
Jdk8:
Jdk8:
package com.interview.javabasic.jvm.model;
public class InternDifference {
public static void main(String[] args) {
String s = new String("a");
s.intern();
String s2 = "a";
System.out.println(s == s2);
String s3 = new String("a") + new String("a");
s3.intern();
String s4 = "aa";
System.out.println(s3 == s4);
}
}
Jdk6:
编译后,在字符串常量池中存在“a”,
New出来的字符串,存放在栈中,与字符串常量的地址肯定不同。
s.intern()想要将new出来的字符串放入到常量池中,由于字符串常量已经存在,所以它们没有关系。
创建s3字符串对象“aa”,由于在字符串常量池中没有“aa”常量,则将字符串对象“aa”的副本放入到字符串常量池中,s4引用常量池中的副本,但是副本与原本并不是同一个对象,它们分别存在于字符串常量池和堆中,所以地址不同。
Jdk6,只能将字符串对象的副本放入到常量池中,而jdk6+,则可以将字符串对象的引用放入到常量池中。
所以,s3的引用存在堆中,s4先去常量池中寻找,找到了s3调用intern()后,存放在常量池中的引用,也就是引用了s3字符串对象,引用的地址相同,返回true。