- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我是一个长期的读者,但第一次写作。
我目前正在尝试在我们的代码库中使用 AspectJ 实现一个记录器。 AspectJ 似乎运行良好,但我遇到了非常奇怪的 Java 错误。我是一名长期的 C++ 和 .Net 开发人员,仍在适应 Java 的世界,所以如果这是一个愚蠢的问题,我深表歉意。
我的代码试图捕获异常,并将相关信息记录到文本文件中。陷阱工作正常,但我注意到在部署时我没有获得任何数据。我在 Java 反编译器中打开了我的类文件,并注意到 PrintWriter 似乎正在生成错误。我从来没有见过这样的问题,所以我希望你能有任何见解。
package mil.uscg.c3cen.vic.aspect;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.JoinPoint;
@Aspect
public class LoggingAspect
{
private final String LOG_FILE = "aspectLog.txt";
private final File file = new File(LOG_FILE);
private LoggingAspect()
{
}
private void logException(String msg)
{
try
{
if(!file.exists())
file.createNewFile();
}
catch(IOException e)
{
}
try (FileWriter fw = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter pw = new PrintWriter(bw))
{
pw.println(msg);
}
catch(IOException e)
{
}
}
private String getSimpleFunctionInfo(String className, String function, Object[] args)
{
StringBuilder builder = new StringBuilder();
builder.append(". Method: ");
builder.append(className);
builder.append(".");
builder.append(function);
if(args.length == 0)
{
builder.append("()");
return builder.toString();
}
builder.append("(");
for(Object o : args)
{
builder.append(o.toString());
builder.append(",");
}
// Replace the comma for the last param with a closing parenthesis
int len = builder.length();
builder.replace(len -1, len, ")");
return builder.toString();
}
// Returns a formatted exception. "Exception.ErrorMessage"
private String getSimpleExceptionInfo(String name, String msg)
{
StringBuilder builder = new StringBuilder();
builder.append("Exception caught: ");
builder.append(name);
builder.append(". Message: ");
builder.append(msg);
return builder.toString();
}
@AfterThrowing(pointcut = "execution(* mil.uscg.c3cen.*.*.*(..)) "
//+ "&& !within(mil.uscg.c3cen.vic.aspect.*) "
, throwing = "excep")
public void afterThrowing(JoinPoint jp, Throwable excep) throws Throwable
{
String ex = getSimpleExceptionInfo(excep.getClass().getSimpleName(),
excep.getMessage());
String name = getSimpleFunctionInfo(jp.getSignature().getDeclaringType().getSimpleName(),
jp.getSignature().getName(),
jp.getArgs());
StringBuilder builder = new StringBuilder();
builder.append(ex);
builder.append(name);
logException(builder.toString());
}
}
除函数 logException 外,类文件中的一切看起来都与您预期的一样。
/* Error */
private void logException(String msg)
{
// Byte code:
// 0: aload_0
// 1: getfield 25 mil/uscg/c3cen/vic/aspect/LoggingAspect:file Ljava/io/File;
// 4: invokevirtual 32 java/io/File:exists ()Z
// 7: ifne +15 -> 22
// 10: aload_0
// 11: getfield 25 mil/uscg/c3cen/vic/aspect/LoggingAspect:file Ljava/io/File;
// 14: invokevirtual 36 java/io/File:createNewFile ()Z
// 17: pop
// 18: goto +4 -> 22
// 21: pop
// 22: aconst_null
// 23: astore_2
// 24: aconst_null
// 25: astore_3
// 26: new 39 java/io/FileWriter
// 29: dup
// 30: aload_0
// 31: getfield 25 mil/uscg/c3cen/vic/aspect/LoggingAspect:file Ljava/io/File;
// 34: invokespecial 41 java/io/FileWriter:<init> (Ljava/io/File;)V
// 37: astore 4
// 39: new 44 java/io/BufferedWriter
// 42: dup
// 43: aload 4
// 45: invokespecial 46 java/io/BufferedWriter:<init> (Ljava/io/Writer;)V
// 48: astore 5
// 50: new 49 java/io/PrintWriter
// 53: dup
// 54: aload 5
// 56: invokespecial 51 java/io/PrintWriter:<init> (Ljava/io/Writer;)V
// 59: astore 6
// 61: aload 6
// 63: aload_1
// 64: invokevirtual 52 java/io/PrintWriter:println (Ljava/lang/String;)V
// 67: aload 6
// 69: ifnull +24 -> 93
// 72: aload 6
// 74: invokevirtual 55 java/io/PrintWriter:close ()V
// 77: goto +16 -> 93
// 80: astore_2
// 81: aload 6
// 83: ifnull +8 -> 91
// 86: aload 6
// 88: invokevirtual 55 java/io/PrintWriter:close ()V
// 91: aload_2
// 92: athrow
// 93: aload 5
// 95: ifnull +43 -> 138
// 98: aload 5
// 100: invokevirtual 58 java/io/BufferedWriter:close ()V
// 103: goto +35 -> 138
// 106: astore_3
// 107: aload_2
// 108: ifnonnull +8 -> 116
// 111: aload_3
// 112: astore_2
// 113: goto +13 -> 126
// 116: aload_2
// 117: aload_3
// 118: if_acmpeq +8 -> 126
// 121: aload_2
// 122: aload_3
// 123: invokevirtual 59 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V
// 126: aload 5
// 128: ifnull +8 -> 136
// 131: aload 5
// 133: invokevirtual 58 java/io/BufferedWriter:close ()V
// 136: aload_2
// 137: athrow
// 138: aload 4
// 140: ifnull +66 -> 206
// 143: aload 4
// 145: invokevirtual 65 java/io/FileWriter:close ()V
// 148: goto +58 -> 206
// 151: astore_3
// 152: aload_2
// 153: ifnonnull +8 -> 161
// 156: aload_3
// 157: astore_2
// 158: goto +13 -> 171
// 161: aload_2
// 162: aload_3
// 163: if_acmpeq +8 -> 171
// 166: aload_2
// 167: aload_3
// 168: invokevirtual 59 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V
// 171: aload 4
// 173: ifnull +8 -> 181
// 176: aload 4
// 178: invokevirtual 65 java/io/FileWriter:close ()V
// 181: aload_2
// 182: athrow
// 183: astore_3
// 184: aload_2
// 185: ifnonnull +8 -> 193
// 188: aload_3
// 189: astore_2
// 190: goto +13 -> 203
// 193: aload_2
// 194: aload_3
// 195: if_acmpeq +8 -> 203
// 198: aload_2
// 199: aload_3
// 200: invokevirtual 59 java/lang/Throwable:addSuppressed (Ljava/lang/Throwable;)V
// 203: aload_2
// 204: athrow
// 205: pop
// 206: return
// Line number table:
// Java source line #28 -> byte code offset #0
// Java source line #29 -> byte code offset #10
// Java source line #30 -> byte code offset #18
// Java source line #31 -> byte code offset #21
// Java source line #36 -> byte code offset #22
// Java source line #36 -> byte code offset #26
// Java source line #37 -> byte code offset #39
// Java source line #38 -> byte code offset #50
// Java source line #40 -> byte code offset #61
// Java source line #41 -> byte code offset #67
// Java source line #42 -> byte code offset #205
// Java source line #46 -> byte code offset #206
// Local variable table:
// start length slot name signature
// 0 207 0 this LoggingAspect
// 0 207 1 msg String
// 23 1 2 localObject1 Object
// 80 28 2 localObject2 Object
// 112 92 2 localObject3 Object
// 25 1 3 localObject4 Object
// 106 17 3 localThrowable1 Throwable
// 151 17 3 localThrowable2 Throwable
// 183 17 3 localThrowable3 Throwable
// 37 140 4 fw java.io.FileWriter
// 48 84 5 bw java.io.BufferedWriter
// 59 28 6 pw java.io.PrintWriter
// 21 1 12 localIOException1 java.io.IOException
// 205 1 13 localIOException2 java.io.IOException
// Exception table:
// from to target type
// 0 18 21 java/io/IOException
// 61 67 80 finally
// 50 93 106 finally
// 39 138 151 finally
// 26 183 183 finally
// 22 205 205 java/io/IOException
}
这真的让我很困惑,所以任何信息都将不胜感激。谢谢!
最佳答案
好的,我尝试使用 Java 8 和当前的 AspectJ 1.8.8。您的方面按预期工作(我编译它时没有任何更改)。它只是有点过于复杂,应该简化。此外,您可能只是错误地计算了切入点中 .*
的数量。
如果我在你的建议方法的开头添加 System.out.println(jp);
以便在控制台上看到一些东西并针对这个示例驱动程序类运行你的方面...
package mil.uscg.c3cen.foo;
public class Application {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
try {
doSomething();
}
catch (Exception e) {}
}
}
public static void doSomething() {
System.out.println("Calculation result = " + multiply(add(3, 4), 5));
System.out.println("Calculation result = " + divide(add(5, 6), 0));
}
private static int add(int summand1, int summand2) {
return summand1 + summand2;
}
private static int multiply(int factor1, int factor2) {
return factor1 * factor2;
}
private static int divide(int dividend, int divisor) {
return dividend / divisor;
}
}
...控制台日志如下所示:
Calculation result = 35
execution(int mil.uscg.c3cen.foo.Application.divide(int, int))
execution(void mil.uscg.c3cen.foo.Application.doSomething())
Calculation result = 35
execution(int mil.uscg.c3cen.foo.Application.divide(int, int))
execution(void mil.uscg.c3cen.foo.Application.doSomething())
Calculation result = 35
execution(int mil.uscg.c3cen.foo.Application.divide(int, int))
execution(void mil.uscg.c3cen.foo.Application.doSomething())
如您所见,只有在调用层次结构中向上抛出异常(直到它们被捕获)的方法才会被记录,正如预期的那样。日志文件 aspectLog.txt 包含以下内容:
Exception caught: ArithmeticException. Message: / by zero. Method: Application.main([Ljava.lang.String;@f6f4d33)
需要改进的地方:
mil.uscg.c3cen
的所有子包为目标。 “该包及其所有子包中的所有方法执行”的语法为 execution(* mil.uscg.c3cen..*(..))
。println
调用之后。改进和简化方面:
package mil.uscg.c3cen.vic.aspect;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class LoggingAspect {
private static final String LOG_FILE = "aspectLog.txt";
private final PrintWriter logWriter;
public LoggingAspect() throws FileNotFoundException {
logWriter = new PrintWriter(new FileOutputStream(LOG_FILE));
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
logWriter.close();
}
});
}
@AfterThrowing(
pointcut =
"(execution(* mil.uscg.c3cen..*(..)) || execution(mil.uscg.c3cen..new(..)))" +
" && !within(mil.uscg.c3cen.vic.aspect..*) ",
throwing = "excep"
)
public void afterThrowing(JoinPoint jp, Throwable excep) throws Throwable {
//System.out.println(excep + " -> " + jp);
logWriter.println(excep + " -> " + jp);
}
}
带有构造函数抛出异常的扩展代码示例:
package mil.uscg.c3cen.foo;
public class Application {
public Application() {
System.out.println(1/0);
}
public static void doSomething() {
System.out.println("Calculation result = " + multiply(add(3, 4), 5));
System.out.println("Calculation result = " + divide(add(5, 6), 0));
}
private static int add(int summand1, int summand2) {
return summand1 + summand2;
}
private static int multiply(int factor1, int factor2) {
return factor1 * factor2;
}
private static int divide(int dividend, int divisor) {
return dividend / divisor;
}
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
try {
doSomething();
}
catch (Exception e) {}
}
try {
new Application();
}
catch (Exception e) {}
}
}
控制台日志:
Calculation result = 35
Calculation result = 35
Calculation result = 35
日志文件:
java.lang.ArithmeticException: / by zero -> execution(int mil.uscg.c3cen.foo.Application.divide(int, int))
java.lang.ArithmeticException: / by zero -> execution(void mil.uscg.c3cen.foo.Application.doSomething())
java.lang.ArithmeticException: / by zero -> execution(int mil.uscg.c3cen.foo.Application.divide(int, int))
java.lang.ArithmeticException: / by zero -> execution(void mil.uscg.c3cen.foo.Application.doSomething())
java.lang.ArithmeticException: / by zero -> execution(int mil.uscg.c3cen.foo.Application.divide(int, int))
java.lang.ArithmeticException: / by zero -> execution(void mil.uscg.c3cen.foo.Application.doSomething())
java.lang.ArithmeticException: / by zero -> execution(mil.uscg.c3cen.foo.Application())
查看最后一行,您会在构造函数中看到异常。
如果您想稍微美化异常日志输出,类似于您原来的方面所做的,请执行以下操作:
logWriter.println(excep.getClass().getSimpleName() + " -> " + jp.getSignature());
然后日志文件变成:
ArithmeticException -> int mil.uscg.c3cen.foo.Application.divide(int, int)
ArithmeticException -> void mil.uscg.c3cen.foo.Application.doSomething()
ArithmeticException -> int mil.uscg.c3cen.foo.Application.divide(int, int)
ArithmeticException -> void mil.uscg.c3cen.foo.Application.doSomething()
ArithmeticException -> int mil.uscg.c3cen.foo.Application.divide(int, int)
ArithmeticException -> void mil.uscg.c3cen.foo.Application.doSomething()
ArithmeticException -> mil.uscg.c3cen.foo.Application()
关于Java PrintWriter 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35581814/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!