问题描述
在我的代码中,我有一个解析日志文件并返回结果列表的方法.没有NonCPS,它可以完美工作并返回正确的值.从管道阶段调用此方法,并且得到了java.io.NotSerializableException:java.util.regex.Matcher,这就是为什么我放置@NonCPS批注的原因.不再抛出异常,但是log_parser方法不能正常工作.现在,它总是返回整个文件-即使删除return result_list.调用此方法的结果始终是文件.
@NonCPS
def log_parser(String filename){
def result_list = []
def match_f, match_s
def lines = readFile(filename).readLines()
for( line in lines ) {
match_f = (line =~ /(?<=Failures: )[^ ]+/ )
match_s = (line =~ /(?<=Skips: )[^ ]+/ )
if( match_f ) {
result_list[1] = (match_f[0]).replace(",", "") }
if( match_s ) {
result_list[2] = (match_s[0]).replace(",", "") }
}
return result_list
}
因为管道会将所有变量(包括函数内部的局部变量)序列化为默认行为,但是java.util.regex.Matcher
无法序列化,所以您会收到错误消息. /p>
选项1)一旦使用完毕,立即释放不可序列化的变量.
def log_parser(String filename){
def result_list = []
def match_f, match_s
def lines = readFile(filename).readLines()
for( line in lines ) {
match_f = (line =~ /(?<=Failures: )[^ ]+/ )
match_s = (line =~ /(?<=Skips: )[^ ]+/ )
if( match_f ) {
result_list[1] = (match_f[0]).replace(",", "")
match_f = null
}
if( match_s ) {
result_list[2] = (match_s[0]).replace(",", "")
match_s = null
}
}
return result_list
}
选项2)将不可序列化的变量移动到带有注释的函数中:@NonCPS
,在@NonCPS函数内部,我们无法调用任何其他管道步骤,因此应该将readFile
从log_pareser()
移出
log_parser(readFile(<log file path>))
@NonCPS
def log_parser(String fileContent){
def result_list = []
def match_f, match_s
def lines = fileContent.readLines()
for( line in lines ) {
match_f = (line =~ /(?<=Failures: )[^ ]+/ )
match_s = (line =~ /(?<=Skips: )[^ ]+/ )
if( match_f ) {
result_list[1] = (match_f[0]).replace(",", "") }
if( match_s ) {
result_list[2] = (match_s[0]).replace(",", "") }
}
return result_list
}
In my code I have a method that parse log file and return list of results. Without NonCPS it works perfect and return correct values. This method is called from pipeline stages and I got java.io.NotSerializableException: java.util.regex.Matcher that's why I put @NonCPS annotation. Exception is not thrown anymore but log_parser method doesnt work well. Now it always return whole file - even if remove return result_list. The result of calling this method is always file.
@NonCPS
def log_parser(String filename){
def result_list = []
def match_f, match_s
def lines = readFile(filename).readLines()
for( line in lines ) {
match_f = (line =~ /(?<=Failures: )[^ ]+/ )
match_s = (line =~ /(?<=Skips: )[^ ]+/ )
if( match_f ) {
result_list[1] = (match_f[0]).replace(",", "") }
if( match_s ) {
result_list[2] = (match_s[0]).replace(",", "") }
}
return result_list
}
Because pipeline will serialize all variables (includes local variable inside function) as default behaviour, but java.util.regex.Matcher
is not serializable, that's why you get the error.
Option 1) release not serializable variable immediately once you complete using it.
def log_parser(String filename){
def result_list = []
def match_f, match_s
def lines = readFile(filename).readLines()
for( line in lines ) {
match_f = (line =~ /(?<=Failures: )[^ ]+/ )
match_s = (line =~ /(?<=Skips: )[^ ]+/ )
if( match_f ) {
result_list[1] = (match_f[0]).replace(",", "")
match_f = null
}
if( match_s ) {
result_list[2] = (match_s[0]).replace(",", "")
match_s = null
}
}
return result_list
}
Option 2) move not serializable variables into function with annotation: @NonCPS
, inside @NonCPS function, we can't call any other pipeline step, therefor you should move readFile
out of log_pareser()
log_parser(readFile(<log file path>))
@NonCPS
def log_parser(String fileContent){
def result_list = []
def match_f, match_s
def lines = fileContent.readLines()
for( line in lines ) {
match_f = (line =~ /(?<=Failures: )[^ ]+/ )
match_s = (line =~ /(?<=Skips: )[^ ]+/ )
if( match_f ) {
result_list[1] = (match_f[0]).replace(",", "") }
if( match_s ) {
result_list[2] = (match_s[0]).replace(",", "") }
}
return result_list
}
这篇关于Groovy Jenkins管道@NonCPSreturn未预期结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!