目录

目录

JMX是什么

JMX架构

MBean

标准MBean

定义接口

实现接口

注册MBean

使用MBean

如何通过Web管理MBean

开放类型MBean

自定义参数

MXBean接口定义

MXBean接口实现

MXBean注册

访问MXBean

动态MBean

如何使用客户端调用MBean



JMX是什么

JMX(Java Management Extensions)是一个为应用程序植入管理功能的标准化代理和服务。通常使用JMX来监控系统的运行状态或管理系统的某些方面,比如清空缓存、重新加载配置文件等。JConsole以及JVisualVM 都是通过JMX来实现对JAVA应用程序的监控。

JMX架构

MBean是JMX中被管理的资源。MBean全部都是由MBeanServer统一管理,并通过MBeanServer对外提供的访问接口提供服务。

MBean

JMX定义了四种类型的MBean,标准MBean,动态MBean,开放MBean和模型MBean

  1. 标准MBean是最简单的实现,他们的管理接口是通过方法名描述的。MXBean是是一种标准的MBean,它使用开放的MBean概念,在简化代码的同事,达到易于管理的目的。
  2. 动态MBean必须实现特定的接口,但是他们在运行时对外提供管理接口,所以具有很大的灵活性。
  3. 开放MBean是动态MBean
  4. 模型MBean也是动态MBean,它是运行时完全可配置和自我描述的。它们为动态设备层资源提供具有默认行为的一般MBean类。

任何一个作为MBean的java实现的java对象,被注册到代理上后,都可以从代理机构的JVM外管理。因此,应用程序中使用JMX只需要两步:

  1. 编写MBean提供管理接口和监控数据
  2. 将MBean注册到MBeanServer

下面本别就四种MBean去看看如何使用

标准MBean

标准MBean是最简单的MBean类型,主要步骤如下:

定义接口

/***定义一个普通的接口** @author zhangwei_david* @version $Id: HiMBean.java, v 0.1 2015年1月24日 下午1:16:15 zhangwei_david Exp $*/
public interface HiMBean {/***打招呼*/public void sayHello();/*** 加法计算器** @param x* @param y* @return*/public int add(int x, int y);/*** 获取名称** @return*/public String getName();/***获取缓存大小** @return*/public int getCacheSize();/***设置缓存大小** @param size*/public void setCacheSize(int size);
}

实现接口


/***简单实现类* @author Lenovo* @version $Id: Hi.java, v 0.1 2014年9月26日 下午2:48:09 Lenovo Exp $*/
public class HiMbeanImpl implements HiMBean {private final String     name               = "Reginald";private int              cacheSize          = DEFAULT_CACHE_SIZE;private static final int DEFAULT_CACHE_SIZE = 200;/*** @see com.cathy.demo.jmx.notifications.HiMBean#sayHello()*/public void sayHello() {System.out.println("Hello," + getName());}/*** @see com.cathy.demo.jmx.notifications.HiMBean#add(int, int)*/public int add(int x, int y) {return x + y;}/*** @see com.cathy.demo.jmx.notifications.HiMBean#getName()*/public String getName() {return name;}/*** @see com.cathy.demo.jmx.notifications.HiMBean#getCacheSize()*/public int getCacheSize() {return cacheSize;}/*** @see com.cathy.demo.jmx.notifications.HiMBean#setCacheSize(int)*/public void setCacheSize(int size) {cacheSize = size;}}

注册MBean

/*** * * @author zhangwei_david* @version $Id: Main.java, v 0.1 2015年6月19日 下午1:10:03 zhangwei_david Exp $*/
public class Main {/**** @param args* @throws Exception*/public static void main(String[] args) throws Exception {//获取Mean的平台服务MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// 对即将被注册的MBean 构造一个ObjectNameObjectName objectName = new ObjectName("com.cathy.demo.jmx:type=Hi");// 创建一个MbeanRequiredModelMBean mbean = new RequiredModelMBean();HiMbeanImpl hiMbean = new HiMbeanImpl();mbean.setManagedResource(hiMbean, "objectReference");ModelMBeanAttributeInfo name = new ModelMBeanAttributeInfo("name", "java.lang.String","userName", true, true, false, new DescriptorSupport(new String[] { "name=name","descriptorType=attribute", "getMethod=getName", "setMethod=setName" }));ModelMBeanOperationInfo sayHello = new ModelMBeanOperationInfo("say Hello", hiMbean.getClass().getMethod("sayHello"));// 创建一个ModelMBeanOperationInfoModelMBeanOperationInfo getName = new ModelMBeanOperationInfo("get userName", hiMbean.getClass().getMethod("getName"));// 使用ModelMbeanAttributeInfo和ModelMbeanOperationInfo构建一个ModelMBeanInfo对象ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport("HiMbean", "Test",new ModelMBeanAttributeInfo[] { name }, null, new ModelMBeanOperationInfo[] { sayHello,getName }, null);// 向ModelMBean 设置ModelMBeanInfombean.setModelMBeanInfo(mbeanInfo);// 将Mbean 注册到MBeanServermbs.registerMBean(mbean, objectName);// 一直等待System.out.println("Waiting forever...");Thread.sleep(Long.MAX_VALUE);}
}

使用MBean

运行后的可以通过jconsole看到MBean

此时可以发现无法通过Web去管理MBean,那么如何通过Web去管理呢?

如何通过Web管理MBean

要想通过Web去管理MBean需要创建一个HtmlAdapterServer,并将其注册到MBeanServer

具体代码示例如下:

/*** Alipay.com Inc.* Copyright (c) 2004-2014 All Rights Reserved.*/
package com.cathy.demo.jmx;import java.lang.management.ManagementFactory;import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import javax.management.modelmbean.RequiredModelMBean;import com.sun.jdmk.comm.HtmlAdaptorServer;/***** @author zhangwei_david* @version $Id: Main.java, v 0.1 2015年6月19日 下午1:10:03 zhangwei_david Exp $*/
public class Main {/**** @param args* @throws Exception*/public static void main(String[] args) throws Exception {//获取Mean的平台服务MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();// 对即将被注册的MBean 构造一个ObjectNameObjectName objectName = new ObjectName("com.cathy.demo.jmx:type=Hi");// 创建一个MbeanRequiredModelMBean mbean = new RequiredModelMBean();HiMbeanImpl hiMbean = new HiMbeanImpl();mbean.setManagedResource(hiMbean, "objectReference");ModelMBeanAttributeInfo name = new ModelMBeanAttributeInfo("name", "java.lang.String","userName", true, true, false, new DescriptorSupport(new String[] { "name=name","descriptorType=attribute", "getMethod=getName", "setMethod=setName" }));ModelMBeanOperationInfo sayHello = new ModelMBeanOperationInfo("say Hello", hiMbean.getClass().getMethod("sayHello"));// 创建一个ModelMBeanOperationInfoModelMBeanOperationInfo getName = new ModelMBeanOperationInfo("get userName", hiMbean.getClass().getMethod("getName"));// 使用ModelMbeanAttributeInfo和ModelMbeanOperationInfo构建一个ModelMBeanInfo对象ModelMBeanInfo mbeanInfo = new ModelMBeanInfoSupport("HiMbean", "Test",new ModelMBeanAttributeInfo[] { name }, null, new ModelMBeanOperationInfo[] { sayHello,getName }, null);// 向ModelMBean 设置ModelMBeanInfombean.setModelMBeanInfo(mbeanInfo);// 将Mbean 注册到MBeanServermbs.registerMBean(mbean, objectName);// 创建一个HtmlAdapterServer MBeanHtmlAdaptorServer htmlAdaptorServer = new HtmlAdaptorServer();// 修改端口号htmlAdaptorServer.setPort(8082);// 将html适配器MBean 注入到MBeanServer,该处port仅仅是描述mbs.registerMBean(htmlAdaptorServer, new ObjectName("Adaptor:name=html,port=8082"));// 启动适配器htmlAdaptorServer.start();// 一直等待System.out.println("Waiting forever...");Thread.sleep(Long.MAX_VALUE);}
}

可以通过 http://localhost:8082/ 访问

点击【type=Hi】进入MBean视图页面

开放类型MBean

开放类型MBean与标准MBean的区别在于接口中引用到一些其他类型的类时的表象方式不同。在MXBean中,如果MXBean的结偶定义了一个自定义属性,当JMX使用这个MXBean时这个类型会被转换成一种标准的类型(CompositeDataSupport),这些类型称之为开发类型。具体代码如下:

自定义参数

/***MXBean参数对象* @author zhangwei_david* @version $Id: QueueSample.java, v 0.1 2015年6月20日 下午4:30:30 zhangwei_david Exp $*/
public class QueueSample {private final Date   date;private final int    size;private final String head;@ConstructorProperties({ "date", "size", "head" })public QueueSample(Date date, int size, String head) {this.date = date;this.size = size;this.head = head;}public Date getDate() {return date;}public int getSize() {return size;}public String getHead() {return head;}
}

MXBean接口定义

/***MXBean接口,定义两个操作** @author zhangwei_david* @version $Id: QueueSamplerMXBean.java, v 0.1 2015年6月20日 下午4:31:34 zhangwei_david Exp $*/
public interface QueueSamplerMXBean {public QueueSample getQueueSample();public void clearQueue();
}

MXBean接口实现

/***MXBean的实现类* @author zhangwei_david* @version $Id: QueueSampler.java, v 0.1 2015年6月20日 下午4:32:19 zhangwei_david Exp $*/
public class QueueSampler implements QueueSamplerMXBean {private Queue<String> queue;public QueueSampler(Queue<String> queue) {this.queue = queue;}public QueueSample getQueueSample() {synchronized (queue) {return new QueueSample(new Date(), queue.size(), queue.peek());}}public void clearQueue() {synchronized (queue) {queue.clear();}}}

MXBean注册

/*** 测试方法* @author zhangwei_david* @version $Id: TestMain.java, v 0.1 2015年6月20日 下午4:33:35 zhangwei_david Exp $*/
public class TestMain {public static void main(String[] args) throws Exception {//获取MBeanServerMBeanServer mbs = ManagementFactory.getPlatformMBeanServer();//构造一个ObjectNameObjectName mxbeanName = new ObjectName("com.example:type=QueueSampler");// 创建一个队列Queue<String> queue = new ArrayBlockingQueue<String>(10);queue.add("Request-1");queue.add("Request-2");queue.add("Request-3");// 构造一个mxbeanQueueSampler mxbean = new QueueSampler(queue);// 注册mxbeanmbs.registerMBean(mxbean, mxbeanName);//等待System.out.println("Waiting for incoming requests...");Thread.sleep(Long.MAX_VALUE);}
}

访问MXBean

动态MBean

动态MBean是运行期才定义它的属性和方法,也就是说它有什么属性和方法都是可以动态改变的。动态MBean是利用一些辅助类(MBeanConstructorInfo,MBeanAtrributeInfo,MBeanOperationInfo)来完成这些功能的。具体代码示例如下:

/*** 动态MBean 示例* * @author zhangwei_david* @version $Id: HelloDynamic.java, v 0.1 2015年6月21日 下午10:53:07 zhangwei_david Exp $*/
public class HelloDynamic implements DynamicMBean {// 管理控件(MBean)属性private String                  name;// 动态创建MBean需要的变量private String                  className   = this.getClass().getName();// 描述private String                  description = "Simple implementation of a dynamic MBean.";//管理资源private MBeanAttributeInfo[]    attributes;// 构造方法private MBeanConstructorInfo[]  constructors;// 操作private MBeanOperationInfo[]    operations;private MBeanInfo               mBeanInfo;// 通知private MBeanNotificationInfo[] notifications;/*** 构造方法*/public HelloDynamic() {init();buildDynamicMBean();}private void init() {className = this.getClass().getName();description = "Simple implementation of a dynamic MBean.";attributes = new MBeanAttributeInfo[1];constructors = new MBeanConstructorInfo[1];operations = new MBeanOperationInfo[1];notifications = new MBeanNotificationInfo[0];}private void buildDynamicMBean() {// 构造方法Constructor<?>[] ctors = this.getClass().getConstructors();constructors[0] = new MBeanConstructorInfo("HelloDynamic(): Constructs a HelloDynamic object", ctors[0]);// 属性attributes[0] = new MBeanAttributeInfo("name", "java.lang.String", "Name: name string",true, true, false);// 方法MBeanParameterInfo[] params = null;operations[0] = new MBeanOperationInfo("print", "print(): print the name", params, "void",MBeanOperationInfo.INFO);// MBeanInfomBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations,notifications);}/**** @see javax.management.DynamicMBean#getAttribute(java.lang.String)*/public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException,ReflectionException {LoggerUtils.info("获取属性:" + attribute);if (attribute == null) {return null;}if ("name".equals(attribute)) {return name;}return null;}public AttributeList getAttributes(String[] attributes) {LoggerUtils.info("获取属性列表" + attributes);if (attributes == null) {return null;}AttributeList reslist = new AttributeList();for (String attr : attributes) {try {Object value = getAttribute(attr);reslist.add(new Attribute(attr, value));} catch (Exception e) {e.printStackTrace();}}return reslist;}/**** @see javax.management.DynamicMBean#getMBeanInfo()*/public MBeanInfo getMBeanInfo() {return mBeanInfo;}/**** @see javax.management.DynamicMBean#invoke(java.lang.String, java.lang.Object[], java.lang.String[])*/public Object invoke(String actionName, Object[] params, String[] signature)throws MBeanException,ReflectionException {LoggerUtils.info(MessageFormat.format("反射调用方法 {0},参数: {1}>签名 {2}", actionName, params,signature));if (actionName.equals("print")) {print();} else if ("dynamicPrint".equals(actionName)) {dynamicPrint();}return null;}/**** @see javax.management.DynamicMBean#setAttribute(javax.management.Attribute)*/public void setAttribute(Attribute attribute) throws AttributeNotFoundException,InvalidAttributeValueException, MBeanException,ReflectionException {if (attribute == null) {return;}String attrname = attribute.getName();Object attrvalue = attribute.getValue();if ("name".equals(attrname)) {if (attrvalue == null) {name = null;} else {try {if (Class.forName("java.lang.String").isAssignableFrom(attrvalue.getClass())) {name = (String) attrvalue;}} catch (ClassNotFoundException e) {e.printStackTrace();}}}}/**** @see javax.management.DynamicMBean#setAttributes(javax.management.AttributeList)*/public AttributeList setAttributes(AttributeList attributes) {if (attributes == null) {return null;}AttributeList reslist = new AttributeList();for (Object obj : attributes) {Attribute attr = (Attribute) obj;try {setAttribute(attr);String attrname = attr.getName();Object attrvalue = attr.getValue();reslist.add(new Attribute(attrname, attrvalue));} catch (Exception e) {e.printStackTrace();}}return reslist;}private void print() {System.out.println(MessageFormat.format("Hello {0}, This is helloDynamic", name));// add method dynamic at runtimeoperations = new MBeanOperationInfo[2];buildDynamicMBean();MBeanParameterInfo[] parameters = null;operations[1] = new MBeanOperationInfo("dynamicPrint","dynamicPrint: Runtime generated by print method", parameters, "void",MBeanOperationInfo.INFO);}private void dynamicPrint() {System.out.println("This is a runtime generated method!");}}
/*** * * @author zhangwei_david* @version $Id: HelloDynamicAgent.java, v 0.1 2015年6月21日 下午10:53:51 zhangwei_david Exp $*/
public class HelloDynamicAgent {private static String DOMAIN = "MyDynamicMBean";/*** @param args* @throws NullPointerException* @throws MalformedObjectNameException* @throws NotCompliantMBeanException* @throws MBeanRegistrationException* @throws InstanceAlreadyExistsException*/public static void main(String[] args) throws MalformedObjectNameException,NullPointerException, InstanceAlreadyExistsException,MBeanRegistrationException, NotCompliantMBeanException {//创建一个MBean服务对象,DOMAIN类似于java里面的公共package部分MBeanServer server = MBeanServerFactory.createMBeanServer(DOMAIN);//创建DynamicMBean对象HelloDynamic hello = new HelloDynamic();//创建一个web适配器服务器,表示我们MBean服务通过web形式来提供给用户管理HtmlAdaptorServer htmlserver = new HtmlAdaptorServer();htmlserver.setPort(9999);//ObjctName对象类似于完整的packageObjectName helloname = new ObjectName(DOMAIN + ":name=HelloDynamic");ObjectName htmlname = new ObjectName(DOMAIN + ":name=HtmlAdaptor");server.registerMBean(hello, helloname);server.registerMBean(htmlserver, htmlname);htmlserver.start();}}
2015-06-21 22:51:17,854 DEBUG LoggerContext[name=sun.misc.Launcher$AppClassLoader@1d16e93, org.apache.logging.log4j.core.LoggerContext@1e7e365] started OK.
2015-06-21 22:51:17,856 DEBUG Using default SystemClock for timestamps
22:51:17.863 [Thread-1] INFO  com.cathy.demo.util.LoggerUtils - 获取属性:name
22:51:21.698 [Thread-1] INFO  com.cathy.demo.util.LoggerUtils - 反射调用方法 print,参数: [Ljava.lang.Object;@107c4b5>签名 [Ljava.lang.String;@a46b89
Hello David, This is helloDynamic

如何使用客户端调用MBean

上文中都是介绍使用Jconsole调用MBean,有没有客户端可以直接调用MBean呢?下面代码就介绍如何使用客户端调用MBean

/*** Alipay.com Inc.* Copyright (c) 2004-2015 All Rights Reserved.*/
package com.cathy.demo.jmx.notifications;import java.lang.management.MemoryUsage;
import java.text.MessageFormat;
import java.util.Set;import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;/**** @author zhangwei_david* @version $Id: ClientTest.java, v 0.1 2015年6月20日 下午4:52:49 zhangwei_david Exp $*/
public class ClientTest {private static final long   KB_SIZE     = 1024;private static final String LOG_PATTERN = "{0}: 分配 {1} KB;  最大值 {2} KB; 已使用 {3} KB;  使用率 {4} %";/**** @param args* @throws Exception*/public static void main(String[] args) throws Exception {JMXServiceURL serviceURL = new JMXServiceURL("service:jmx:rmi://localhost/jndi/rmi://localhost:9999/jmxrmi");JMXConnector jmxc = JMXConnectorFactory.connect(serviceURL);MBeanServerConnection msc = jmxc.getMBeanServerConnection();// 获取所有的ObjectNameSet<ObjectName> objectNames = msc.queryNames(null, null);for (ObjectName objectName : objectNames) {System.out.println("ObjectName:" + objectName.getCanonicalName() + ".");}ObjectName name = new ObjectName("java.lang:type=OperatingSystem");System.out.println(msc.getAttributes(name, new String[] { "CommittedVirtualMemorySize","FreePhysicalMemorySize", "FreeSwapSpaceSize" }));printLog(msc, "java.lang:name=Metaspace,type=MemoryPool","java.lang:name=Survivor Space,type=MemoryPool","java.lang:name=Eden Space,type=MemoryPool","java.lang:name=Code Cache,type=MemoryPool","java.lang:name=Tenured Gen,type=MemoryPool");}private static void printLog(MBeanServerConnection msc, String... name) throws Exception {for (String string : name) {log(string, getUsageByName(msc, string));}}private static MemoryUsage getUsageByName(MBeanServerConnection msc, String name)throws Exception {return MemoryUsage.from((CompositeDataSupport) msc.getAttribute(new ObjectName(name),"Usage"));}private static void log(String key, MemoryUsage usage) {System.out.println();System.out.println(MessageFormat.format(LOG_PATTERN, key, usage.getCommitted() / KB_SIZE,usage.getMax() / KB_SIZE, usage.getUsed() / KB_SIZE,usage.getUsed() * 100 / usage.getCommitted()));}
}

运行的结果是:

ObjectName:java.lang:name=Metaspace,type=MemoryPool.
ObjectName:java.lang:name=Eden Space,type=MemoryPool.
ObjectName:java.lang:name=Survivor Space,type=MemoryPool.
ObjectName:java.lang:name=Copy,type=GarbageCollector.
ObjectName:JMImplementation:type=MBeanServerDelegate.
ObjectName:java.lang:type=Runtime.
ObjectName:java.lang:type=Threading.
ObjectName:java.lang:type=OperatingSystem.
ObjectName:java.lang:name=MarkSweepCompact,type=GarbageCollector.
ObjectName:java.lang:name=Code Cache,type=MemoryPool.
ObjectName:java.nio:name=direct,type=BufferPool.
ObjectName:java.lang:type=Compilation.
ObjectName:java.lang:name=Tenured Gen,type=MemoryPool.
ObjectName:java.lang:name=CodeCacheManager,type=MemoryManager.
ObjectName:java.lang:type=Memory.
ObjectName:java.nio:name=mapped,type=BufferPool.
ObjectName:java.util.logging:type=Logging.
ObjectName:java.lang:type=ClassLoading.
ObjectName:java.lang:name=Metaspace Manager,type=MemoryManager.
ObjectName:com.sun.management:type=DiagnosticCommand.
ObjectName:com.sun.management:type=HotSpotDiagnostic.
[CommittedVirtualMemorySize = 33554432, FreePhysicalMemorySize = 3817508864, FreeSwapSpaceSize = 9955905536]java.lang:name=Metaspace,type=MemoryPool: 分配 5,120 KB;  最大值 0 KB; 已使用 5,025 KB;  使用率 98 %java.lang:name=Survivor Space,type=MemoryPool: 分配 512 KB;  最大值 8,704 KB; 已使用 0 KB;  使用率 0 %java.lang:name=Eden Space,type=MemoryPool: 分配 4,480 KB;  最大值 69,952 KB; 已使用 1,244 KB;  使用率 27 %java.lang:name=Code Cache,type=MemoryPool: 分配 992 KB;  最大值 32,768 KB; 已使用 961 KB;  使用率 96 %java.lang:name=Tenured Gen,type=MemoryPool: 分配 10,944 KB;  最大值 174,784 KB; 已使用 1,915 KB;  使用率 17 %

JMX详解以及使用示例相关推荐

  1. python字典的用法_Python字典的用法详解(附示例)

    本篇文章给大家带来的内容是关于Python字典的用法详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 字典的表现形式为:{key:value},键和值之间用冒号分隔,每个 ...

  2. java集合框架的结构_集合框架(Collections Framework)详解及代码示例

    简介 集合和数组的区别: 数组存储基础数据类型,且每一个数组都只能存储一种数据类型的数据,空间不可变. 集合存储对象,一个集合中可以存储多种类型的对象.空间可变. 严格地说,集合是存储对象的引用,每个 ...

  3. java学习 类变量 类方法_这篇文章主要介绍了JAVA类变量及类方法代码实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下类变量(...

    这篇文章主要介绍了JAVA类变量及类方法代码实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 类变量(static) 类变量是该类的所有对象共 ...

  4. Freesurfer recon-all命令详解及使用示例

    Freesurfer recon-all命令详解及使用示例 一.一些名词解释 atlas 模板,带标签的地图 CA Canonical 典型的,规范的(CA Normalize, CA Registe ...

  5. 用计算机函数查找,Excel查找函数Vlookup详解及应用示例-excel技巧-电脑技巧收藏家...

    Excel查找函数Vlookup详解及应用示例 招如其名.此招用来在一个茫茫的数据源中,自动让电脑找出你要的某个数据的相关资料并填在指定的地方.也是就是,可以让电脑在一个表格或指定的一个区域中查找某一 ...

  6. 三维空间刚体运动1:旋转矩阵与变换矩阵(详解加代码示例)

    三维空间刚体运动1:旋转矩阵与变换矩阵(详解加代码示例) 1. 点.向量和坐标系 2.坐标系间的欧式变换 2.1 旋转 2.2 平移 3.齐次坐标和变换矩阵 4. 相似.仿射和射影变换 4.1 相似变 ...

  7. 如何使用计算机Excel公式if,Excel条件函数If详解及应用示例-excel技巧-电脑技巧收藏家...

    Excel条件函数If详解及应用示例 此招用来对某一条件执行的真假值进行判断,根据逻辑计算的真假值,返回不同结果.如果结果为真,则返回一个真,如果为假,则返回另一值,可谓左右逢源. 使用语法 IF(l ...

  8. Python线性规划库Pulp的详解及应用示例

    Python线性规划库Pulp的详解及应用示例 线性规划是一种常见的优化方法,在商业.工程等领域有着广泛的应用.而Python作为一种高效.灵活的编程语言,也提供了丰富的线性规划库可供选择.本文将介绍 ...

  9. java log4配置例子,log4j.properties配置属性详解与配置示例

    log4j.properties配置属性详解与配置示例 发布时间:2018-03-27作者:laosun阅读(1535) log4j.properties配置属性详解与配置示例,拿走直接用!详细解答了 ...

最新文章

  1. MASM32_SDKv10以及一些帮大家打包的东西
  2. Dockerfile 简版大全,附赠编写实例
  3. 算法练习day2——190319(大顶堆、冒泡、选择、插入)
  4. 机器学习-k均值聚类算法-k_means原理14
  5. C++中常量成员函数的含义
  6. 解决 Script Error 的另类思路
  7. vfp程序转换为c语言程序软件,c语言程序设计及vfp程序设计试题.doc
  8. JS的条形码和二维码生成
  9. Maven生命周期和插件的那些事(2021版)
  10. wms策略文档_内容策略:技术文档的新理念
  11. 大家马致远是哪个朝代的,马致远作品赏析
  12. 为什么 a==true 和 a==false 结果都是false ?
  13. vue 打包后本地先自己启动服务 anywhere 非常好用
  14. 28个超有用的PPT小技巧,快来收藏
  15. 使用Python一键获取百度网盘提取码
  16. 阿里云docker提交及删除入门操作
  17. 笔记本外接显示器闪屏
  18. uClinux on Blackfin BF533 STAMP - A DSP Linux Port
  19. 用ZBrush做游戏建模,3D打印,手办模型、珠宝设计等
  20. Pytorch实现多层lstm

热门文章

  1. 荔枝派Zero(V3s)SPI Flash 启动
  2. pygame飞机大战
  3. Java中print 和 println区别
  4. 2017福州大学面向对象程序设计课程作业四
  5. day11 Java 面向对象 final 多态
  6. js原生实现高性能懒加载(分步解析)
  7. 尹语堂1333公益 2021-07-31
  8. Solidity 中 receive 函数 和 callback函数分析
  9. jquery添加important样式
  10. 好用的电竞蓝牙耳机推荐