jvm高级特性第4章-虚拟机性能监控与故障处理工具

【4.2】jdk命令行工具

1、jps:虚拟机进程状况工具;

C:\Users\pacoson>jps -l // 输出主类名称
12272 sun.tools.jps.Jps
12736 chapter3.Page93
2808C:\Users\pacoson>jps -v // 查看虚拟机进程启动时的参数
12736 Page93 -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -Dfile.encoding=UTF-8
2808  -Dosgi.requiredJavaVersion=1.6 -Xms40m -Xmx512m -Dgrails.console.enable.interactive=false -Dgrails.console.enable.terminal=false -Djline.terminal=jline.UnsupportedTerminal -Dgrails.console.class=grails.build.logging.GrailsEclipseConsole
6072 Jps -Dapplication.home=D:\Java\jdk1.8.0_172 -Xms8mC:\Users\pacoson>jps // 列出正在运行的虚拟机进程 
12736 Page93
2808
7992 Jps

补充:

jps -q 仅输出本地虚拟机唯一id, LVMID;

jps -m 输出虚拟机启动时传递给主类的main函数的参数;

jps可以通过rmi 协议查看开启了rmi服务的远程虚拟机进程状态 ; 

2、jstat:虚拟机统计信息监视工具(java statistics monitoring tool)

C:\Users\pacoson>jstat -gcutil 12736 1000 20 // 每隔1000毫秒查看虚拟机12736的内存使用率,共查看20次S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT0.00   0.00  52.00  64.89  53.87  54.43      6    0.015     8    0.405    0.4210.00   0.00  52.00  64.89  53.87  54.43      6    0.015     8    0.405    0.4210.00   0.00  52.00  64.89  53.87  54.43      6    0.015     8    0.405    0.4210.00   0.00  52.00  64.89  53.87  54.43      6    0.015     8    0.405    0.421

S0=Survivor0, S=Suivivor1, E=Eden区域, O=Old区域, YGC=Young GC=收集年轻代次数=6, YGCT=0.015秒(年轻代收集耗时), FGC=Full GC=老年代收集次数=8, FGCT=Full GC Time=老年代收集耗时=0.421; 

3、jinfo:java配置信息工具: 实时查看和调整虚拟机各项参数;

C:\Users\pacoson>jps // 查看本地java虚拟机id
12736 Page93
11496 Jps
2808C:\Users\pacoson>jinfo -flags //查看虚拟机参数 
Usage:jinfo [option] <pid>(to connect to running process)jinfo [option] <executable <core>(to connect to a core file)jinfo [option] [server_id@]<remote server IP or hostname>(to connect to remote debug server)where <option> is one of:-flag <name>         to print the value of the named VM flag-flag [+|-]<name>    to enable or disable the named VM flag // +启用/-停用-flag <name>=<value> to set the named VM flag to the given value // 设置参数值-flags               to print VM flags-sysprops            to print Java system properties<no option>          to print both of the above-h | -help           to print this help messageC:\Users\pacoson>
C:\Users\pacoson>jinfo -flags 12736
Attaching to process ID 12736, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.172-b11
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=20971520 -XX:MaxHeapSize=20971520 -XX:MaxNewSize=10485760 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=10485760 -XX:OldSize=10485760 -XX:+PrintGC -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -Dfile.encoding=UTF-8

4、jmap:java内存映像工具,用于生成堆转储快照文件,一般称为heapdump 或 dump文件(堆转储快照文件)

使用-XX:+HeapDumpOnOutOfMemoryError参数,可以让jvm在oom异常出现之后自动生成dump文件; 

jmap在windows平台下的功能是受限的; 

jmap和jhat连用以查看虚拟机堆转储快照如下:

5、jhat:虚拟机堆转储快照分析工具;jvm Heap Analysis Tool,与jmap搭配使用;(不推荐使用jhat命令分析dump文件)

推荐的分析堆转储快照工具有:VisualVM, Eclipse Memory Analyzer, IBM HeapAnalyzer等工具;

C:\Users\pacoson>jmap -dump:format=b,file=eclipse.bin 12736  // 生成jvm12736的堆转储快照文件
Dumping heap to C:\Users\pacoson\eclipse.bin ...
File existsC:\Users\pacoson>
C:\Users\pacoson>jhat eclipse.bin // 启用内嵌web服务器分析eclpse.bin 文件(访问localhost:7000)
Reading from eclipse.bin...
Dump file created Tue May 07 23:43:59 CST 2019
Snapshot read, resolving...
Resolving 7066 objects...
Chasing references, expect 1 dots.
Eliminating duplicate references.
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.

6、jstack:java堆栈跟踪工具

jstack=stack trace for java, 用于生成虚拟机当前时刻的线程快照(一般称为threaddump文件或 javacore文件);

线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程死锁,死循环,请求外部资源超时等;

C:\Users\pacoson>jstack -l 12736  // 查看12736进程堆栈信息
2019-05-12 20:55:41
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.172-b11 mixed mode):"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001557f000 nid=0x794 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C1 CompilerThread3" #9 daemon prio=9 os_prio=2 tid=0x0000000015505000 nid=0x36e8 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C2 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x00000000154fe000 nid=0x3ab4 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x00000000154f1000 nid=0x32b4 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x0000000015499000 nid=0x16e4 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x0000000015498000 nid=0x578 waiting on condition [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000154ef800 nid=0x5b0 runnable [0x0000000000000000]java.lang.Thread.State: RUNNABLELocked ownable synchronizers:- None"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000015480800 nid=0x2c3c in Object.wait() [0x000000001595f000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x00000000fec08a78> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)- locked <0x00000000fec08a78> (a java.lang.ref.ReferenceQueue$Lock)at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)Locked ownable synchronizers:- None"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001357d000 nid=0x103c in Object.wait() [0x000000001545f000]java.lang.Thread.State: WAITING (on object monitor)at java.lang.Object.wait(Native Method)- waiting on <0x00000000fec01158> (a java.lang.ref.Reference$Lock)at java.lang.Object.wait(Object.java:502)at java.lang.ref.Reference.tryHandlePending(Reference.java:191)- locked <0x00000000fec01158> (a java.lang.ref.Reference$Lock)at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)Locked ownable synchronizers:- None"main" #1 prio=5 os_prio=0 tid=0x0000000002f2d800 nid=0x780 waiting on condition [0x0000000002a8f000]java.lang.Thread.State: TIMED_WAITING (sleeping)at java.lang.Thread.sleep(Native Method)at chapter3.Page93.minorGC(Page93.java:24)at chapter3.Page93.main(Page93.java:10)Locked ownable synchronizers:- None"VM Thread" os_prio=2 tid=0x0000000013578000 nid=0x3350 runnable"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002df7800 nid=0x3958 runnable"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002df9000 nid=0x4a7c runnable"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002dfa800 nid=0xcdc runnable"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002dfc000 nid=0x3a2c runnable"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002dfe800 nid=0x3b30 runnable"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002dff800 nid=0x3a0 runnable"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002e02800 nid=0x2a0 runnable"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002e05000 nid=0x1ed4 runnable"VM Periodic Task Thread" os_prio=2 tid=0x00000000155ae000 nid=0x35e8 waiting on conditionJNI global references: 5

可以通过调用 Thread.getAllStackTraces() 方法完成 jstack的大部分功能;

【荔枝】

/*** Thread.getAllStackTraces获取虚拟机中所有线程的StackTraceElement对象* , 模拟jstack的大部分功能   */
public class Page111 {public static void main(String[] args) {for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println(new Random(17).nextInt(10)); } }).start(); // // 启动线程 }for (int i = 0; i < 3600; i++) {System.out.println("================");try {Thread.sleep(1000);/* Thread.getAllStackTraces获取虚拟机中所有线程的StackTraceElement对象  */Map<Thread, StackTraceElement[]> stackTracks = Thread.getAllStackTraces();for (Map.Entry<Thread, StackTraceElement[]> entry : stackTracks.entrySet()) {System.out.println("key = " + entry.getKey().getName() + ", value = " + entry.getValue());StackTraceElement[] elements = entry.getValue();int index = 1;for (StackTraceElement e : elements) {System.out.println("value[" + index++ +"] = " + e);}}} catch (InterruptedException e) {e.printStackTrace();}}}
}
// Thread.getAllStackTraces获取虚拟机中所有线程的StackTraceElement对象,线程方法堆栈信息
key = Finalizer, value = [Ljava.lang.StackTraceElement;@5c647e05
value[1] = java.lang.Object.wait(Native Method)
value[2] = java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
value[3] = java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
value[4] = java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
key = Attach Listener, value = [Ljava.lang.StackTraceElement;@33909752
key = Signal Dispatcher, value = [Ljava.lang.StackTraceElement;@55f96302
key = Reference Handler, value = [Ljava.lang.StackTraceElement;@3d4eac69
value[1] = java.lang.Object.wait(Native Method)
value[2] = java.lang.Object.wait(Object.java:502)
value[3] = java.lang.ref.Reference.tryHandlePending(Reference.java:191)
value[4] = java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
key = main, value = [Ljava.lang.StackTraceElement;@42a57993
value[1] = java.lang.Thread.dumpThreads(Native Method)
value[2] = java.lang.Thread.getAllStackTraces(Thread.java:1610)
value[3] = chapter4.Page111.main(Page111.java:25)

7、HSDIS:JIT生成代码反汇编

HSDIS是一个sun官方推荐的hotspot虚拟机 JIT编译代码的反汇编插件,包含在hotspot虚拟机的源码之中,但没有提供编译后的程序。

作用是让hotspot的-XX:+PrintAssembly 指令调用它来吧动态生成的本地代码还原为汇编代码输出,同时还生成了大量有价值的注释;

 

【4.3】JDK的可视化工具

JConsole和VisualVM;JConsole是虚拟机监控工具, 而VisualVM是多合一故障处理工具;

1、JConsole:java监视与管理控制台;基于JMX的可视化监视,管理工具;

1.1、启动JConsole;

【JConsole监控荔枝】

/*** JConsole 监控jvm内存  * vm params: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8*/
public class Page114JConsoleTest {private static final int _1MB = 1024 * 1024;public static void main(String[] args) {for (int i = 0; i < 3600; i++) {new Thread(new Runnable() {@Overridepublic void run() {byte[] allocation1 = new byte[1 * _1MB]; byte[] allocation2 = new byte[2 * _1MB];byte[] allocation4 = new byte[4 * _1MB];} }).start(); // // 启动线程try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace(); }}}
}

1.2、内存监控

/*** JConsole监视代码 * jvm params: -Xms100m -Xmx100m -XX:+UseSerialGC* @author tang rong* 2019/05/12 */
public class Page117 {public static void main(String[] args) throws Exception {fillHeap(1000);}public static void fillHeap(int num) throws InterruptedException {List<OOMObject> list = new ArrayList<>(); for (int i=0; i<num; i++) {System.out.println(i);/* 稍作延时,令监视曲线的变化更加明显 */Thread.sleep(50);list.add(new OOMObject());}System.gc();  }static class OOMObject {byte[] placeholder = new byte[64 * 1024];} 
}

1.3、线程监控

线程长时间停顿的主要原因有: 等待外部资源(数据库连接,网络资源,设备资源等),死循环,锁等待(活锁和死锁);

【荔枝-线程等待演示代码】

/*** 线程等待演示代码* @author tr* 2019/05/12 */
public class Page119 {public static void createBusyThread() {new Thread(new Runnable() {@Overridepublic void run() {while (true) // 死循环;}}, "testBusyThread").start();}public static void createLockThread(final Object lock) {new Thread(new Runnable() {@Overridepublic void run() {synchronized (lock) {try {lock.wait(); // 线程等待 } catch (InterruptedException e) {e.printStackTrace();}}}}, "testLockThread").start(); }public static void main(String[] args) throws Exception {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));br.readLine();createBusyThread(); // 死循环br.readLine();Object obj = new Object(); createLockThread(obj); // 线程等待}
}

【荔枝-线程死锁等待演示代码】

/*** 线程死锁等待演示 * @author tr* 2019/05/12 */
public 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++) {System.out.println("i = " + i);new Thread(new SynAddRunnable(1, 2)).start(); // 死锁, 线程1拿到了a锁,准备拿b锁,但线程2拿到了b锁且没有释放;new Thread(new SynAddRunnable(2, 1)).start(); // 死锁,线程2拿到了b锁,准备拿a锁,但线程1拿到了a锁且没有释放;} }
}

出现死锁后,查看线程列表中被阻塞的线程;

 

【4.3.2】VisualVM:多合一故障处理工具(jvisualvm.exe)

1、VisualVM可以做到:

显示jvm进程配置信息,环境信息(jps, jinfo);

监视cpu, gc,堆,方法区以及线程信息(jstat, jstack);

dump以及分析堆转储快照(jmap,jhat);

方法级的程序运行性能分析,找出被调用最多,运行时间最长的方法;

离线程序快照:收集程序的运行时配置,线程dump,内存dump等信息建立一个快照,可以将快照发送给开发者;

其他plugin的无限可能性;

【补充】VisualVM的兼容性

如果不给VisualVM安装插件,就放弃了其最精华的功能;

2、生成、浏览堆转储快照-dump文件

点击堆dump;

3、分析程序性能:profiler页签中分析;

注意: profiling堆程序运行性能有很大影响,一般不在生产环境做;

4、BTrace动态日志跟踪

4.1、BTrace的作用是:在不停止目标程序运行的前提下,通过hotspot虚拟机的hotswap技术动态加入原本并不存在的调试代码(如日志信息);

补充:hotswap技术,即代码热替换技术, hotspot虚拟机允许在不停止运行的情况下,更新已经加载的类的代码;

/*** BTrace 跟踪演示 * @date 2019/05/13*/
public class BTraceTest {public int add(int a, int b) {return a + b; }public static void main(String[] args) throws IOException {BTraceTest test = new BTraceTest();BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));for (int i = 0; i < 10; i++) {                                                                                                                                                                                                                                                                                                                reader.readLine();int a = (int) Math.round(Math.random() * 1000);int b = (int) Math.round(Math.random() * 1000);System.out.println("test.add(a, b) = " + test.add(a, b));}}
}

trace script

/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;@BTrace
public class TracingScript {/* put your code here */@OnMethod(clazz = "chapter4.BTraceTest",method = "add",location = @Location(Kind.RETURN))public static void func(@Self chapter4.BTraceTest instance,int a,int b,@Return int result){println("调用堆栈:");jstack();println(strcat("方法参数A:",str(a)));println(strcat("方法参数B:",str(b)));println(strcat("方法结果:",str(result)));    }
}

BTrace的用法包括: 打印调用堆栈,参数,返回值只是最基本的应用,还可以进行性能监视,定位连接泄漏和内存泄漏,解决多线程竞争问题等;

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSP引入CSS文件无法生效的问题

JSP引入CSS文件无法生效的问题 开发工具与关键技术&#xff1a;eclipse、Java 作者&#xff1a;幻奏 撰写时间&#xff1a;2020.8.8不知道你们有没有碰到这个问题&#xff0c;就是css文件在jsp中无法生效&#xff0c;看解决办法的可以直接看下下面&#xff0c;前面只是我碰到…

Maven精选系列--classifier元素妙用

转载自 Maven精选系列--classifier元素妙用 先来看这么一个依赖 <dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.4</version> </dependency> 看似没问题吧&#xff1f;你觉得能…

IDEA创建Spring配置文件Spring Config的方法

作为刚刚开始学Spring框架的小白&#xff0c;而且我也是刚刚学怎么用idea&#xff0c;不会简单的操作也是很正常的是吧。这个问题其实只是我傻傻的不懂&#xff0c;是个很简单的问题&#xff0c;我现在把它记录下来。 在idea创建maven项目后&#xff0c;我们在左边右键新建xml文…

Maven精选系列--POM文件解析

转载自 Maven精选系列--POM文件解析 之前有介绍到maven的标准目录结构&#xff0c;也看到了maven的核心配置文件pom.xml文件&#xff0c;今天就解析这个配置文件。 maven工程的核心文件就是这个pom文件了&#xff0c;每个工程在创建的时候都会有一个pom.xml配置文件&#xff0c…

JVM参数设置、分析(转)

转自&#xff1a;http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html 不管是YGC还是Full GC,GC过程中都会对导致程序运行中中断,正确的选择不同的GC策略,调整JVM、GC的参数&#xff0c;可以极大的减少由于GC工作&#xff0c;而导致的程序运行中断方面的问题&a…

如何下载、配置IDEA的Maven

我们每个项目都会用到jar包&#xff0c;而maven就是我们经常使用到的一个jar包的管理工具&#xff0c;下面我就来说说maven是如何配置在我们的电脑上的。 第一步当然是在官网下载maven啦&#xff0c;下面是官网的连接 http://maven.apache.org/download.cgi 下载好了就解压在…

Maven精选系列--eclipse各种操作

转载自 Maven精选系列--eclipse各种操作 在eclipse中配置maven的安装目录&#xff0c;使用最新的maven插件&#xff0c;从安装列表中可以看到eclipse自带绑定的是3.3.9&#xff0c;不是最新的&#xff0c;我们勾选自己的最新的。 在eclipse中设置maven的配置文件settings.xml路…

win7-elasticsearch环境搭建

【写在前面】 &#xff08;模拟&#xff09;es客户端共有4种&#xff1a; 1、postman&#xff1b; 2、kibana&#xff1b; 3、curl&#xff1b; 4、api&#xff0c; 如java api&#xff1b; 【1】下载elasticsearch windows version 和 kibana window version https://w…

IDEA中配置mybatis

之前我们用maven创建了项目&#xff0c;接着我来写下怎么在idea中配置mybatis。 第一步我们先把mybatis、sql驱动的依赖先导进去&#xff0c;接着在&#xff0c;main文件夹下面新建一个resources文件夹&#xff0c;再到下面新建一个mybatis.xml文件作为mybatis的主配置文件。 …

Spring的核心模块解析

转载自 Spring的核心模块解析 Spring框架是一个轻量级的集成式开发框架&#xff0c;可以和任何一种框架集成在一起使用&#xff0c;可以说是一个大的全家桶。Spring从1.x发展到现在的5.x可以说是越来越强大&#xff0c;下面来看看Spring都包含哪些核心的模块吧。 Spring图中的这…

no [query] registered for [filtered] in es7 的解决方法

转自 https://blog.csdn.net/wslyk606/article/details/78896023 使用es查询条件为&#xff1a; POST /_search { "query": { "filtered": { "query": { "query_string": { …

控制台查出数据传到layui数据表格却没有数据的问题

最近在试着用ssm整合的框架来做一个新的项目&#xff0c;然后用idea做了一个多表查询&#xff0c;结果发现有某一条数据没有正常显示出来&#xff0c;这让我着急的到网上找了好久都没有答案&#xff08;可能是我不太聪明&#xff09;如下图 明明其他的都有数据了&#xff0c…

一张图搞懂Spring bean的完整生命周期

转载自 一张图搞懂Spring bean的完整生命周期 一张图搞懂Spring bean的生命周期&#xff0c;从Spring容器启动到容器销毁bean的全过程&#xff0c;包括下面一系列的流程&#xff0c;了解这些流程对我们想在其中任何一个环节怎么操作bean的生成及修饰是非常有帮助的。 Bean的完整…

React学习途径和资料分享

转自&#xff1a; https://www.jianshu.com/p/de421e0db710 这段时间因为项目的原因&#xff0c;要做web前端&#xff0c;趁此机会调研了一下当前前端的技术&#xff0c;根据调研的结果&#xff0c;React毫无疑问是现在的NO.1&#xff0c;遂决定入坑学一下React。 工欲善其事…

Mysql外键约束怎么删除

记录一下碰到的问题。由于我是使用PowerDesigner来建mysql物理模型的&#xff0c;为了表与表之间的关系更加清楚&#xff0c;我给他们连线了。之后我就用它生成的SQL语句在navicat把表建出来&#xff0c;我看见没问题就直接用了&#xff0c;毕竟初学者嘛&#xff0c;嘿嘿。 到我…

Spring AOP注解为什么失效?90%Java程序员不知道

转载自 Spring AOP注解为什么失效&#xff1f;90%Java程序员不知道 使用Spring Aop注解的时候&#xff0c;如Transactional, Cacheable等注解一般需要在类方法第一个入口的地方加&#xff0c;不然不会生效。 如下面几种场景 1、Controller直接调用Service A方法&#xff1a;…

mybatis多表新增如何获取主键ID

记录一下碰到的问题&#xff0c;就当做是笔记吧&#xff0c;防止忘记。在做ssm多表新增的时候&#xff0c;碰到了一个小问题&#xff0c;就是在新增成功一个表的时候我要获取它的ID&#xff0c;然后用它的ID新增下一个表。 但是&#xff0c;我要怎么做呢&#xff1f;新增成功&a…

React 相关的优秀资源

转自&#xff1a; https://github.com/ywwhack/react-journey React 相关的优秀资源 以下列出的资源主要来自自己学习react过程中看过的觉的不错的文章、教程&#xff0c;也算是一个学习过程的记录。 React 教程 名称简介fullstackreact如果只看一个react教程&#xff0c;…

Spring import配置文件使用占位符

转载自 Spring import配置文件使用占位符 import使用占位符 连接池切换导入配置的代码&#xff1a; <import resource"classpath:META-INF/spring/spring-${db.connection.pool}.xml" /> 在配置文件添加配置 db.connection.pooldruid 启动直接报错&#xff0c;…

i18n国际化登录页面

国际化是啥&#xff0c;一开始我也是一脸懵逼。了解了之后才知道&#xff0c;原来它相当于网站的翻译按钮。毕竟世界上有很多不同的语言&#xff0c;不可能每个人都会中文嘛&#xff0c;所以它的作用就体现出来了。 国际化又被称为i18n&#xff0c;因为internationalization(国…