一、java开发和运行过程
- 编写:用编写工具,编写.java文件
- 编译:采用javac.exe工具对.java文件进行编译,产生.class文件
- 运行:采用java.exe加载.class文件运行。
运行过程详解:
- 加载:首先通过ClassLoader进行加载,
- 存储:加载之后放入JVM Memory中来,
- 执行:执行机获取memory中的东西,获取字节码指令,然后翻译为本地方法执行。
class文件依赖于JVM,JVM基于OS。都是多对一的关系。
运行管理可分为:jvm管理,os管理。
二、os管理:
- 进程级别的管理(黑盒)
- cpu/内存/io等具体性能监控
Linux平台:
- top命令:查看系统中最占资源的部分
- vmstat命令:查看系统的整体cpu/内存/io/Swap等信息
- iostat命令:查看系统详细的IO信息
windows平台:
- 运行平台的 任务管理器进行概览
- 在运行中输入perfmon,打开性能监视器,跟踪进程。
三、jvm管理:
- 线程/程序级别的管理(白盒)
- 查看虚拟机运行时的各项信息。
- 跟踪程序的执行过程,查看程序运行时的信息。
- 限制程序对资源的使用
- 将内存导出为文件进行具体分析
3.1命令行的管理工具
vmid为线程号。
jstatd主要是程序提供对外暴露的代理。
客户机通过ip地址加端口号来查看,远程机通过jstatd来发布。
例子:查看120548,查看java进行的虚拟机的参数。
3.2可视化工具:
JConsole(jdk自带,命令行运行打开)/Visual VM/MIssion Control三大工具。具体用法可百度。
3.3、JMX
一个为应用程序植入管理功能的框架,用户可以在任何java应用程序中使用这些代理和服务实现。
jmx的架构:
MBean
代表一个被管理的对象,类似于javaBean,对外暴露一个管理接口,即一些可读/写的属性,一些可操作的方法。
分为四类:stanfard MBean/dynamic MBean/open MBean/model Mbean
stanfard MBean:标准的MBean,定义一个接口SomethingMBean ,和实现类Something。
Agent
一个MBean的容器,代表群被管理的对象.外界通过Agent可以访问到MBean。Agent的核心是MBeanServer,MBean在MBeanServer中注册。Agent也包含一个通讯适配器或者连接器使得外界的管理工具可以接入。
实例实现:
package com.example.mbeans;
public interface HelloMBean {
// operations
public void sayHello();
public int add(int x, int y);
// attributes
// a read-only attribute called Name of type String
public String getName();
// a read-write attribute called CacheSize of type int
public int getCacheSize();
public void setCacheSize(int size);
}
package com.example.mbeans;
/* Hello.java - MBean implementation for the Hello World MBean.
This class must implement all the Java methods declared in the
HelloMBean interface, with the appropriate behavior for each one. */
public class Hello implements HelloMBean {
public void sayHello() {
System.out.println("hello, world");
}
public int add(int x, int y) {
return x + y;
}
/*
* Getter for the Name attribute. The pattern shown here is frequent: the getter
* returns a private field representing the attribute value. In our case, the
* attribute value never changes, but for other attributes it might change as
* the application runs. Consider an attribute representing statistics such as
* uptime or memory usage, for example. Being read-only just means that it can't
* be changed through the management interface.
*/
public String getName() {
return this.name;
}
/*
* Getter for the CacheSize attribute. The pattern shown here is frequent: the
* getter returns a private field representing the attribute value, and the
* setter changes that field.
*/
public int getCacheSize() {
return this.cacheSize;
}
/*
* Setter for the CacheSize attribute. To avoid problems with stale values in
* multithreaded situations, it is a good idea for setters to be synchronized.
*/
public synchronized void setCacheSize(int size) {
this.cacheSize = size;
/*
* In a real application, changing the attribute would typically have effects
* beyond just modifying the cacheSize field. For example, resizing the cache
* might mean discarding entries or allocating new ones. The logic for these
* effects would be here.
*/
System.out.println("Cache size now " + this.cacheSize);
}
private final String name = "Reginald";
private int cacheSize = DEFAULT_CACHE_SIZE;
private static final int DEFAULT_CACHE_SIZE = 200;
}
package com.example.mbeans;
/* Main.java - main class for Hello World example. Create the
HelloWorld MBean, register it, then wait forever (or until the
program is interrupted). */
import java.lang.management.*;
import javax.management.*;
public class Main {
/*
* For simplicity, we declare "throws Exception". Real programs will usually
* want finer-grained exception handling.
*/
public static void main(String[] args) throws Exception {
// Get the Platform MBean Server
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
// Construct the ObjectName for the MBean we will register
ObjectName name = new ObjectName("com.example.mbeans:type=Hello");
// Create the Hello World MBean
Hello mbean = new Hello();
// Register the Hello World MBean
mbs.registerMBean(mbean, name);
// Wait forever
System.out.println("Waiting forever...");
Thread.sleep(Long.MAX_VALUE);
}
}
控制操作:
运行Main函数,命令行输入Jconsole打开可视化管理工具,通过连接正在运行的MBean。
3.4、java运行安全工具
java程序可能来自网络和第三方jar包,所以要做一定的防护。防止这些程序非法访问某些目录、打开Socket链接、退出虚拟机等。
Java提供安全管理器
- 对程序行为进行安全判定,若违反则报错。
- 架子啊安全策略文件,一个权限的姐,规定哪些程序可以做哪些功能
- 默认情况下,普通程序不加载安全管理器的。
- 启用安全管理器:
安全策略文件:
- 建立代码来源和访问权限的关系。
- 代码来源为代码位置和证书集。
- 权限:建立tmp目录下设置权限
- 安全策略文件中写:
- 代码中写:
1.使用安全策略文件:
import java.io.File;
public class FileTest {
public static void main(String[] args) {
System.setProperty("java.security.policy","file:E:/java/source/PMOOC13-07/dist.policy");//安全策略文件的地址
System.setSecurityManager(new SecurityManager());//设置安全管理器
File f = new File("F:/temp/1.txt");
if(f.exists()){
f.delete();
}
}
}
安全策略文件。read,write,delete进行附权。
grant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission;
};
grant {
permission java.io.FilePermission "F:/temp/-", "read,write,delete";//展示temp目录下文件只能读写删除权限
};
2.代码中定义安全策略:
import java.security.Permission;
import java.security.Policy;
import java.security.ProtectionDomain;
public class NetworkPolicy extends Policy{
private final Permission permissions;
public NetworkPolicy(Permission permissions) {
this.permissions = permissions;
}
@Override
public boolean implies(ProtectionDomain domain, Permission permission) {
return permissions.implies(permission);
}
}
赋予了监听权限,如果删除listen则不能进行监听。
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketPermission;
import java.security.Permissions;
import java.security.Policy;
public class NetworkTest {
public static void main(String[] args) {
testListen();
}
public static void testListen() {
// connect, listen, accept, resolve
SocketPermission p = new SocketPermission("localhost:80", "listen,resolve");
//规定Socket权限在本机80端口监听服务,如果删除listen则报错
//本程序无法在80端口监听
Permissions ps = new Permissions();//jdk自带的Permission类
ps.add(p);//这段代码我没看懂....哭泣
Policy.setPolicy(new NetworkPolicy(p));
System.setSecurityManager(new SecurityManager());//加载安全策略管理器
try {
ServerSocket server = new ServerSocket(80);
Socket socket = server.accept();
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(bytes)) != -1) {
sb.append(new String(bytes, 0, len, "UTF-8"));
}
System.out.println(sb.toString());
is.close();
socket.close();
server.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、堆文件分析
jmap生成到e盘的文件,扩展名记得是hprof,堆信息快照保存。
jhat则是解析hprof文件,解析之后会通过网页http的形式展示,本机打开浏览器访问本机的7000端口就可以打开。它也可以支持OQL方法查询,类似于SQL语法,可以快速查询对象。
Visual VM可视化管理工具也可以分析堆文件。
Eclipse MAT也可以分析堆文件。可以独立运行,也可以安装到Eclipse中。
参考中国大学mooc《java核心技术》