05 JVM和GC.txt

UP 返回
1.反编译代码
  1.1 创建项目javabasic,src下创建包com.dm.bytecode,包下创建类ByteCodeSample
		public class ByteCodeSample {
		    public static void main(String[] args) {
		        int i=1,j=5;
		        i++;
		        ++j;
		        System.out.println(i);
		        System.out.println(j);
		    }
		}
  1.2 打开idea控制台(或者用系统的也行),执行:
		cd src														进入目录下
		javac com/dm/bytecode/ByteCodeSample.java			编译(此时会在目录下生成ByteCodeSample.class文件) 
		javap -c com/dm/bytecode/ByteCodeSample.class		反编译(此时会打印出反编译出来的代码)

			Compiled from "ByteCodeSample.java"														说明由ByteCodeSample.java编译而来
			public class com.dm.bytecode.ByteCodeSample {
			  public com.dm.bytecode.ByteCodeSample();												编译生成的缺省无参构造函数
			    Code:																						code表示该方法的代码如下
			       0: aload_0																					this句柄,表示对this进行操作
			       1: invokespecial #1                  // Method java/lang/Object."<init>":()V					调用父类的构造方法(注释里说明了其父类为Object)
			       4: return																					退出方法
			
			  public static void main(java.lang.String[]);													main函数及其参数为String数组
			    Code:
			       0: iconst_1																				把常量1放到栈顶
			       1: istore_1																					将栈顶的值1放到局部变量1中
			       2: iconst_5																				把常量5放到栈顶
			       3: istore_2																					将栈顶的值5放到局部变量2中
			       4: iinc          1, 1																			将变量1加1
			       7: iinc          2, 1																		    	将变量2加1
			      10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;			getstatic来获取PrintStream的静态域对象,将其压入栈顶
			      13: iload_1																					iload_1	将本地变量1的值推入栈顶
			      14: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V					调用PrintStream.println方法打印
			      17: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
			      20: iload_2																					对变量2同样进行上述操作
			      21: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
			      24: return
			}
  1.3 java跨平台的实现:
	.java文件通过javac编译,生成.class字节码文件;字节码文件会被各个平台的JVM解析,转换成特定平台的执行指令。演示如下:
		ssh root@192.168.0.108					win平台上可以通过ssh命令登录其他服务器,这里表示以root登录192.168.0.108,输入密码以后即可操作对应电脑
		scp ByteCodeSample.class root@192.168.0.108:~			进入之前编译的bytecode文件夹下,使用scp可以将指定路径下的文件ByteCodeSample.class传入以root用户登录进192.168.0.108的用户目录下(~即表示用户目录,稍后输入密码即可执行操作)
																		scp需要两边电脑同时支持,如果服务器的linux是最简安装则不支持该命令,需要使用yum install openssh-clients安装即可
		mkdir -p com/dm/bytecode							进入目标服务器,创建文件夹com/dm/bytecode(因为之前就是在该路径下编译产生的class,所以这里的文件也要放在同样的文件夹下才能被执行,否则会报找不到主类的错)
		cp ByteCodeSample.class com/dm/bytecode/			将ByteCodeSample.class移进com/dm/bytecode/文件夹下(当前目录是用户目录~)
		java com.dm.bytecode.ByteCodeSample				执行,可以发现打印出了2和6,跨平台成功
	
2 虚拟机
  2.1 java虚拟机的结构,分为4大部分:
	Class Loader
	Runtime Data Area(JVM内存空间结构模型。Stack,Heap,Method Area,PC Register,Native Method Stack)
	Execution Engine
	Native Interface(本地接口。融合不同的编程语言为java所用)

	Class Loader依据特定格式,将class文件加载到内存(只要符合格式即加载,能不能运行由Execution Engine管);Execution Engine负责对class文件里的字节码进行解析并交给操作系统执行。
  2.2 ClassLoader
	ClassLoader负责通过将Class文件里的二进制数据流装载进系统,然后交给Java虚拟机进行连接初始化等操作
	

3 反射
  创建类:
	package com.dm.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;
	    }
	}
  在main中运用反射:
	public class ReflectSample {
	    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
	        Class rc = Class.forName("com.dm.reflect.Robot");
	        Robot r = (Robot) rc.newInstance();
	        System.out.println("Class name is " + rc.getName());
	        Method getHello = rc.getDeclaredMethod("throwHello", String.class);//能获取类中除了继承和实现的接口的其他所有方法,包括私有
	        getHello.setAccessible(true);//私有方法需要设置
	        Object str = getHello.invoke(r, "Bob");
	        System.out.println("getHello result is " + str);
	        Method sayHi = rc.getMethod("sayHi", String.class);//只能获取公共的方法,但是可以获取继承以及实现的方法
	        sayHi.invoke(r, "Welcome");
	        Field name = rc.getDeclaredField("name");
	        name.setAccessible(true);
	        name.set(r, "Alice");
	        sayHi.invoke(r, "Welcome");
	    }
	}

















DOWN 返回