我对 Java 很陌生。我正在构建一个数组列表来保存 Git 提交中的部分文本。我在 Jenkins 内的 Groovy 脚本中运行它。
def commits = sh script: """ git log ${previous_tag}..HEAD --oneline --decorate""", returnStdout: true
def array = commits.split("\\n");
ArrayList<String> mystats = new ArrayList<>(array.length);
for(int i =0; i < array.length; i++) {
Pattern pattern = Pattern.compile("^\\w{7}\\s(MYSTATS-|mystats-)");
Matcher matcher = pattern.matcher(array[i]);
if(matcher.find()) {
mystats.add(array[i])
}
}
然后我想做的是创建另一个数组来保存唯一值(因此不要重复任何内容),并且被告知 HashSet 是最好的方法,因为它会拒绝重复的值
// Put all unique mystats matches into a set
Set<String> mystats_set = new HashSet<String>(mystats.size());
for(int i =0; i < mystats.size(); i++) {
Pattern pattern = Pattern.compile("(MYSTATS-|mystats-)\\w+");
Matcher matcher = pattern.matcher(mystats[i]);
if(matcher.find()) {
String id = matcher.group().toUpperCase().toString();
def jira_json = sh script: '''curl --cert ../certs/dev_cert.p12:password https://jira.dev.organisation.co.uk:port_number/rest/api/2/issue/${id}''', returnStdout: true
mystats_set.add("[" + id + "](https://jira.dev.organisation.co.uk/browse/" + id + ")");
}
}
当它运行时,我得到
java.io.NotSerializableException: java.util.regex.Matcher
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:860)
at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
at java.util.HashMap.internalWriteEntries(HashMap.java:1785)
at java.util.HashMap.writeObject(HashMap.java:1362)
at sun.reflect.GeneratedMethodAccessor202.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:967)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
at java.util.TreeMap.writeObject(TreeMap.java:2438)
at sun.reflect.GeneratedMethodAccessor204.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:976)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1032)
at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:988)
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:854)
at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.writeObject(RiverWriter.java:132)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:429)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:408)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:356)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$100(CpsThreadGroup.java:78)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:236)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:224)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:47)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:112)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
原因:发生的异常: 在现场本地人 在字段父级中 在现场调用者中 在字段 e 实地计划 在现场线程中 在对象 org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@4f76de19
经过一番阅读后,似乎 Set
不可序列化?如果是这种情况,我怎样才能拥有一个仅保存唯一值并拒绝重复条目的 ArrayList?
最佳答案
好吧,添加完整的堆栈跟踪后,现在看来 Matcher
是问题所在,因为它不可序列化
你检查过吗this ?
我引用:
you would have noticed a problem:
java.io.NotSerializableException: java.util.regex.Matcher This occurs because the matcher local variable is of a type (Matcher) not considered serializable by Java. Since pipelines must survive Jenkins restarts, the state of the running program is periodically saved to disk so it can be resumed later (saves occur after every step or in the middle of steps such as sh). ...
查看链接以获取更多信息
这篇文章建议对声明 Matcher
的方法使用注释 @NonCPS
。因为我再次引用:
Such a method will be treated as “native” by the Pipeline engine, and its local variables never saved
例如,
@NonCPS
public void doSomeWork(){
ArrayList<String> mystats = new ArrayList<>(array.length);
for(int i =0; i < array.length; i++) {
Pattern pattern = Pattern.compile("^\\w{7}\\s(MYSTATS-|mystats-)");
Matcher matcher = pattern.matcher(array[i]);
if(matcher.find()) {
mystats.add(array[i])
}
}
}
对于使用 Matcher
的代码的第二部分也是如此
基于您发布的答案的另一个解决方案,使用 transient
您必须在方法之外声明 Matcher
才能使用 transient
我不确定您的代码的上下文,或者您是否可以声明 Matcher
并在稍后使用它,例如:
transient Matcher matcher = null;
def commits = sh script: """ git log ${previous_tag}..HEAD --oneline --decorate""", returnStdout: true
def array = commits.split("\\n");
ArrayList<String> mystats = new ArrayList<>(array.length);
for(int i =0; i < array.length; i++) {
Pattern pattern = Pattern.compile("^\\w{7}\\s(MYSTATS-|mystats-)");
matcher = pattern.matcher(array[i]);
if(matcher.find()) {
mystats.add(array[i])
}
}
代码的第二部分也是如此,除非它们位于同一类(范围)中,否则无需重新声明 Matcher
关于java - ArrayList 中字符串的唯一实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41124238/