Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
arthas-master
Commits
7c094a26
Commit
7c094a26
authored
Dec 18, 2023
by
liang.tang
Browse files
arthas-master
parents
Pipeline
#220
failed with stages
in 0 seconds
Changes
361
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1929 additions
and
0 deletions
+1929
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/ResetCommand.java
...om/taobao/arthas/core/command/basic1000/ResetCommand.java
+60
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/SessionCommand.java
.../taobao/arthas/core/command/basic1000/SessionCommand.java
+49
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/StopCommand.java
...com/taobao/arthas/core/command/basic1000/StopCommand.java
+42
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/SystemEnvCommand.java
...aobao/arthas/core/command/basic1000/SystemEnvCommand.java
+63
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/SystemPropertyCommand.java
.../arthas/core/command/basic1000/SystemPropertyCommand.java
+77
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/TeeCommand.java
.../com/taobao/arthas/core/command/basic1000/TeeCommand.java
+47
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java
...taobao/arthas/core/command/basic1000/VMOptionCommand.java
+110
-0
core/src/main/java/com/taobao/arthas/core/command/basic1000/VersionCommand.java
.../taobao/arthas/core/command/basic1000/VersionCommand.java
+28
-0
core/src/main/java/com/taobao/arthas/core/command/express/ArthasObjectPropertyAccessor.java
...as/core/command/express/ArthasObjectPropertyAccessor.java
+25
-0
core/src/main/java/com/taobao/arthas/core/command/express/ClassLoaderClassResolver.java
...arthas/core/command/express/ClassLoaderClassResolver.java
+45
-0
core/src/main/java/com/taobao/arthas/core/command/express/CustomClassResolver.java
...obao/arthas/core/command/express/CustomClassResolver.java
+43
-0
core/src/main/java/com/taobao/arthas/core/command/express/Express.java
.../java/com/taobao/arthas/core/command/express/Express.java
+52
-0
core/src/main/java/com/taobao/arthas/core/command/express/ExpressException.java
.../taobao/arthas/core/command/express/ExpressException.java
+30
-0
core/src/main/java/com/taobao/arthas/core/command/express/ExpressFactory.java
...om/taobao/arthas/core/command/express/ExpressFactory.java
+33
-0
core/src/main/java/com/taobao/arthas/core/command/express/OgnlExpress.java
...a/com/taobao/arthas/core/command/express/OgnlExpress.java
+73
-0
core/src/main/java/com/taobao/arthas/core/command/hidden/JulyCommand.java
...va/com/taobao/arthas/core/command/hidden/JulyCommand.java
+105
-0
core/src/main/java/com/taobao/arthas/core/command/hidden/ThanksCommand.java
.../com/taobao/arthas/core/command/hidden/ThanksCommand.java
+24
-0
core/src/main/java/com/taobao/arthas/core/command/klass100/ClassDumpTransformer.java
...ao/arthas/core/command/klass100/ClassDumpTransformer.java
+90
-0
core/src/main/java/com/taobao/arthas/core/command/klass100/ClassLoaderCommand.java
...obao/arthas/core/command/klass100/ClassLoaderCommand.java
+729
-0
core/src/main/java/com/taobao/arthas/core/command/klass100/DumpClassCommand.java
...taobao/arthas/core/command/klass100/DumpClassCommand.java
+204
-0
No files found.
Too many changes to show.
To preserve performance only
361 of 361+
files are displayed.
Plain diff
Email patch
core/src/main/java/com/taobao/arthas/core/command/basic1000/ResetCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.taobao.arthas.core.advisor.Enhancer
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.model.ResetModel
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.matcher.Matcher
;
import
com.taobao.arthas.core.util.SearchUtils
;
import
com.taobao.arthas.core.util.affect.EnhancerAffect
;
import
com.taobao.middleware.cli.annotations.Argument
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Option
;
import
com.taobao.middleware.cli.annotations.Summary
;
import
java.lang.instrument.Instrumentation
;
import
java.lang.instrument.UnmodifiableClassException
;
/**
* 恢复所有增强类<br/>
*
* @author vlinux on 15/5/29.
*/
@Name
(
"reset"
)
@Summary
(
"Reset all the enhanced classes"
)
@Description
(
Constants
.
EXAMPLE
+
" reset\n"
+
" reset *List\n"
+
" reset -E .*List\n"
)
public
class
ResetCommand
extends
AnnotatedCommand
{
private
String
classPattern
;
private
boolean
isRegEx
=
false
;
@Argument
(
index
=
0
,
argName
=
"class-pattern"
,
required
=
false
)
@Description
(
"Path and classname of Pattern Matching"
)
public
void
setClassPattern
(
String
classPattern
)
{
this
.
classPattern
=
classPattern
;
}
@Option
(
shortName
=
"E"
,
longName
=
"regex"
,
flag
=
true
)
@Description
(
"Enable regular expression to match (wildcard matching by default)"
)
public
void
setRegEx
(
boolean
regEx
)
{
isRegEx
=
regEx
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
Instrumentation
inst
=
process
.
session
().
getInstrumentation
();
Matcher
matcher
=
SearchUtils
.
classNameMatcher
(
classPattern
,
isRegEx
);
try
{
EnhancerAffect
enhancerAffect
=
Enhancer
.
reset
(
inst
,
matcher
);
process
.
appendResult
(
new
ResetModel
(
enhancerAffect
));
process
.
end
();
}
catch
(
UnmodifiableClassException
e
)
{
// ignore
process
.
end
();
}
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/SessionCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.taobao.arthas.core.command.model.SessionModel
;
import
com.taobao.arthas.core.server.ArthasBootstrap
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.shell.session.Session
;
import
com.taobao.arthas.core.util.UserStatUtil
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
import
com.alibaba.arthas.tunnel.client.TunnelClient
;
/**
* 查看会话状态命令
*
* @author vlinux on 15/5/3.
*/
@Name
(
"session"
)
@Summary
(
"Display current session information"
)
public
class
SessionCommand
extends
AnnotatedCommand
{
@Override
public
void
process
(
CommandProcess
process
)
{
SessionModel
result
=
new
SessionModel
();
Session
session
=
process
.
session
();
result
.
setJavaPid
(
session
.
getPid
());
result
.
setSessionId
(
session
.
getSessionId
());
//tunnel
TunnelClient
tunnelClient
=
ArthasBootstrap
.
getInstance
().
getTunnelClient
();
if
(
tunnelClient
!=
null
)
{
String
id
=
tunnelClient
.
getId
();
if
(
id
!=
null
)
{
result
.
setAgentId
(
id
);
}
result
.
setTunnelServer
(
tunnelClient
.
getTunnelServerUrl
());
result
.
setTunnelConnected
(
tunnelClient
.
isConnected
());
}
//statUrl
String
statUrl
=
UserStatUtil
.
getStatUrl
();
result
.
setStatUrl
(
statUrl
);
process
.
appendResult
(
result
);
process
.
end
();
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/StopCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.taobao.arthas.core.command.model.MessageModel
;
import
com.taobao.arthas.core.command.model.ResetModel
;
import
com.taobao.arthas.core.command.model.ShutdownModel
;
import
com.taobao.arthas.core.server.ArthasBootstrap
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.affect.EnhancerAffect
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* @author hengyunabc 2019-07-05
*/
@Name
(
"stop"
)
@Summary
(
"Stop/Shutdown Arthas server and exit the console."
)
public
class
StopCommand
extends
AnnotatedCommand
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
StopCommand
.
class
);
@Override
public
void
process
(
CommandProcess
process
)
{
shutdown
(
process
);
}
private
static
void
shutdown
(
CommandProcess
process
)
{
ArthasBootstrap
arthasBootstrap
=
ArthasBootstrap
.
getInstance
();
try
{
// 退出之前需要重置所有的增强类
process
.
appendResult
(
new
MessageModel
(
"Resetting all enhanced classes ..."
));
EnhancerAffect
enhancerAffect
=
arthasBootstrap
.
reset
();
process
.
appendResult
(
new
ResetModel
(
enhancerAffect
));
process
.
appendResult
(
new
ShutdownModel
(
true
,
"Arthas Server is going to shutdown..."
));
}
catch
(
Throwable
e
)
{
logger
.
error
(
"An error occurred when stopping arthas server."
,
e
);
process
.
appendResult
(
new
ShutdownModel
(
false
,
"An error occurred when stopping arthas server."
));
}
finally
{
process
.
end
();
arthasBootstrap
.
destroy
();
}
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/SystemEnvCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.model.SystemEnvModel
;
import
com.taobao.arthas.core.shell.cli.Completion
;
import
com.taobao.arthas.core.shell.cli.CompletionUtils
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.StringUtils
;
import
com.taobao.middleware.cli.annotations.Argument
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* @author hengyunabc 2018-11-09
*
*/
@Name
(
"sysenv"
)
@Summary
(
"Display the system env."
)
@Description
(
Constants
.
EXAMPLE
+
" sysenv\n"
+
" sysenv USER\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"sysenv"
)
public
class
SystemEnvCommand
extends
AnnotatedCommand
{
private
String
envName
;
@Argument
(
index
=
0
,
argName
=
"env-name"
,
required
=
false
)
@Description
(
"env name"
)
public
void
setOptionName
(
String
envName
)
{
this
.
envName
=
envName
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
try
{
SystemEnvModel
result
=
new
SystemEnvModel
();
if
(
StringUtils
.
isBlank
(
envName
))
{
// show all system env
result
.
putAll
(
System
.
getenv
());
}
else
{
// view the specified system env
String
value
=
System
.
getenv
(
envName
);
result
.
put
(
envName
,
value
);
}
process
.
appendResult
(
result
);
process
.
end
();
}
catch
(
Throwable
t
)
{
process
.
end
(-
1
,
"Error during setting system env: "
+
t
.
getMessage
());
}
}
/**
* First, try to complete with the sysenv command scope. If completion is
* failed, delegates to super class.
*
* @param completion
* the completion object
*/
@Override
public
void
complete
(
Completion
completion
)
{
CompletionUtils
.
complete
(
completion
,
System
.
getenv
().
keySet
());
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/SystemPropertyCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.model.MessageModel
;
import
com.taobao.arthas.core.command.model.SystemPropertyModel
;
import
com.taobao.arthas.core.shell.cli.Completion
;
import
com.taobao.arthas.core.shell.cli.CompletionUtils
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.StringUtils
;
import
com.taobao.middleware.cli.annotations.Argument
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* @author ralf0131 2017-01-09 14:03.
*/
@Name
(
"sysprop"
)
@Summary
(
"Display, and change the system properties."
)
@Description
(
Constants
.
EXAMPLE
+
" sysprop\n"
+
" sysprop file.encoding\n"
+
" sysprop production.mode true\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"sysprop"
)
public
class
SystemPropertyCommand
extends
AnnotatedCommand
{
private
String
propertyName
;
private
String
propertyValue
;
@Argument
(
index
=
0
,
argName
=
"property-name"
,
required
=
false
)
@Description
(
"property name"
)
public
void
setOptionName
(
String
propertyName
)
{
this
.
propertyName
=
propertyName
;
}
@Argument
(
index
=
1
,
argName
=
"property-value"
,
required
=
false
)
@Description
(
"property value"
)
public
void
setOptionValue
(
String
propertyValue
)
{
this
.
propertyValue
=
propertyValue
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
try
{
if
(
StringUtils
.
isBlank
(
propertyName
)
&&
StringUtils
.
isBlank
(
propertyValue
))
{
// show all system properties
process
.
appendResult
(
new
SystemPropertyModel
(
System
.
getProperties
()));
}
else
if
(
StringUtils
.
isBlank
(
propertyValue
))
{
// view the specified system property
String
value
=
System
.
getProperty
(
propertyName
);
if
(
value
==
null
)
{
process
.
end
(
1
,
"There is no property with the key "
+
propertyName
);
return
;
}
else
{
process
.
appendResult
(
new
SystemPropertyModel
(
propertyName
,
value
));
}
}
else
{
// change system property
System
.
setProperty
(
propertyName
,
propertyValue
);
process
.
appendResult
(
new
MessageModel
(
"Successfully changed the system property."
));
process
.
appendResult
(
new
SystemPropertyModel
(
propertyName
,
System
.
getProperty
(
propertyName
)));
}
process
.
end
();
}
catch
(
Throwable
t
)
{
process
.
end
(-
1
,
"Error during setting system property: "
+
t
.
getMessage
());
}
}
/**
* First, try to complete with the sysprop command scope.
* If completion is failed, delegates to super class.
* @param completion the completion object
*/
@Override
public
void
complete
(
Completion
completion
)
{
CompletionUtils
.
complete
(
completion
,
System
.
getProperties
().
stringPropertyNames
());
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/TeeCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.middleware.cli.annotations.*
;
/**
* @author min.yang
*/
@Name
(
"tee"
)
@Summary
(
"tee command for pipes."
)
@Description
(
Constants
.
EXAMPLE
+
" sysprop | tee /path/to/logfile | grep java \n"
+
" sysprop | tee -a /path/to/logfile | grep java \n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"tee"
)
public
class
TeeCommand
extends
AnnotatedCommand
{
private
String
filePath
;
private
boolean
append
;
@Argument
(
index
=
0
,
argName
=
"file"
,
required
=
false
)
@Description
(
"File path"
)
public
void
setFilePath
(
String
filePath
)
{
this
.
filePath
=
filePath
;
}
@Option
(
shortName
=
"a"
,
longName
=
"append"
,
flag
=
true
)
@Description
(
"Append to file"
)
public
void
setRegEx
(
boolean
append
)
{
this
.
append
=
append
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
process
.
end
(-
1
,
"The tee command only for pipes. See 'tee --help'"
);
}
public
String
getFilePath
()
{
return
filePath
;
}
public
boolean
isAppend
()
{
return
append
;
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/VMOptionCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
java.lang.management.ManagementFactory
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.sun.management.HotSpotDiagnosticMXBean
;
import
com.sun.management.VMOption
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.model.ChangeResultVO
;
import
com.taobao.arthas.core.command.model.MessageModel
;
import
com.taobao.arthas.core.command.model.VMOptionModel
;
import
com.taobao.arthas.core.shell.cli.Completion
;
import
com.taobao.arthas.core.shell.cli.CompletionUtils
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.StringUtils
;
import
com.taobao.middleware.cli.annotations.Argument
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* vmoption command
*
* @author hengyunabc 2019-09-02
*
*/
// @formatter:off
@Name
(
"vmoption"
)
@Summary
(
"Display, and update the vm diagnostic options."
)
@Description
(
"\nExamples:\n"
+
" vmoption\n"
+
" vmoption PrintGC\n"
+
" vmoption PrintGC true\n"
+
" vmoption PrintGCDetails true\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"vmoption"
)
//@formatter:on
public
class
VMOptionCommand
extends
AnnotatedCommand
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
VMOptionCommand
.
class
);
private
String
name
;
private
String
value
;
@Argument
(
index
=
0
,
argName
=
"name"
,
required
=
false
)
@Description
(
"VMOption name"
)
public
void
setOptionName
(
String
name
)
{
this
.
name
=
name
;
}
@Argument
(
index
=
1
,
argName
=
"value"
,
required
=
false
)
@Description
(
"VMOption value"
)
public
void
setOptionValue
(
String
value
)
{
this
.
value
=
value
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
run
(
process
,
name
,
value
);
}
private
static
void
run
(
CommandProcess
process
,
String
name
,
String
value
)
{
try
{
HotSpotDiagnosticMXBean
hotSpotDiagnosticMXBean
=
ManagementFactory
.
getPlatformMXBean
(
HotSpotDiagnosticMXBean
.
class
);
if
(
StringUtils
.
isBlank
(
name
)
&&
StringUtils
.
isBlank
(
value
))
{
// show all options
process
.
appendResult
(
new
VMOptionModel
(
hotSpotDiagnosticMXBean
.
getDiagnosticOptions
()));
}
else
if
(
StringUtils
.
isBlank
(
value
))
{
// view the specified option
VMOption
option
=
hotSpotDiagnosticMXBean
.
getVMOption
(
name
);
if
(
option
==
null
)
{
process
.
end
(-
1
,
"In order to change the system properties, you must specify the property value."
);
return
;
}
else
{
process
.
appendResult
(
new
VMOptionModel
(
Collections
.
singletonList
(
option
)));
}
}
else
{
VMOption
vmOption
=
hotSpotDiagnosticMXBean
.
getVMOption
(
name
);
String
originValue
=
vmOption
.
getValue
();
// change vm option
hotSpotDiagnosticMXBean
.
setVMOption
(
name
,
value
);
process
.
appendResult
(
new
MessageModel
(
"Successfully updated the vm option."
));
process
.
appendResult
(
new
VMOptionModel
(
new
ChangeResultVO
(
name
,
originValue
,
hotSpotDiagnosticMXBean
.
getVMOption
(
name
).
getValue
())));
}
process
.
end
();
}
catch
(
Throwable
t
)
{
logger
.
error
(
"Error during setting vm option"
,
t
);
process
.
end
(-
1
,
"Error during setting vm option: "
+
t
.
getMessage
());
}
}
@Override
public
void
complete
(
Completion
completion
)
{
HotSpotDiagnosticMXBean
hotSpotDiagnosticMXBean
=
ManagementFactory
.
getPlatformMXBean
(
HotSpotDiagnosticMXBean
.
class
);
List
<
VMOption
>
diagnosticOptions
=
hotSpotDiagnosticMXBean
.
getDiagnosticOptions
();
List
<
String
>
names
=
new
ArrayList
<
String
>(
diagnosticOptions
.
size
());
for
(
VMOption
option
:
diagnosticOptions
)
{
names
.
add
(
option
.
getName
());
}
CompletionUtils
.
complete
(
completion
,
names
);
}
}
core/src/main/java/com/taobao/arthas/core/command/basic1000/VersionCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.basic1000
;
import
com.taobao.arthas.core.command.model.VersionModel
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ArthasBanner
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* 输出版本
*
* @author vlinux
*/
@Name
(
"version"
)
@Summary
(
"Display Arthas version"
)
public
class
VersionCommand
extends
AnnotatedCommand
{
@Override
public
void
process
(
CommandProcess
process
)
{
VersionModel
result
=
new
VersionModel
();
result
.
setVersion
(
ArthasBanner
.
version
());
process
.
appendResult
(
result
);
process
.
end
();
}
}
core/src/main/java/com/taobao/arthas/core/command/express/ArthasObjectPropertyAccessor.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
import
java.util.Map
;
import
com.taobao.arthas.core.GlobalOptions
;
import
ognl.ObjectPropertyAccessor
;
import
ognl.OgnlException
;
/**
*
* @author hengyunabc 2022-03-24
*
*/
public
class
ArthasObjectPropertyAccessor
extends
ObjectPropertyAccessor
{
@Override
public
Object
setPossibleProperty
(
Map
context
,
Object
target
,
String
name
,
Object
value
)
throws
OgnlException
{
if
(
GlobalOptions
.
strict
)
{
throw
new
IllegalAccessError
(
GlobalOptions
.
STRICT_MESSAGE
);
}
return
super
.
setPossibleProperty
(
context
,
target
,
name
,
value
);
}
}
core/src/main/java/com/taobao/arthas/core/command/express/ClassLoaderClassResolver.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
ognl.ClassResolver
;
/**
*
* @author hengyunabc 2018-10-18
* @see ognl.DefaultClassResolver
*/
public
class
ClassLoaderClassResolver
implements
ClassResolver
{
private
ClassLoader
classLoader
;
private
Map
<
String
,
Class
<?>>
classes
=
new
ConcurrentHashMap
<
String
,
Class
<?>>(
101
);
public
ClassLoaderClassResolver
(
ClassLoader
classLoader
)
{
this
.
classLoader
=
classLoader
;
}
@Override
public
Class
<?>
classForName
(
String
className
,
@SuppressWarnings
(
"rawtypes"
)
Map
context
)
throws
ClassNotFoundException
{
Class
<?>
result
=
null
;
if
((
result
=
classes
.
get
(
className
))
==
null
)
{
try
{
result
=
classLoader
.
loadClass
(
className
);
}
catch
(
ClassNotFoundException
ex
)
{
if
(
className
.
indexOf
(
'.'
)
==
-
1
)
{
result
=
Class
.
forName
(
"java.lang."
+
className
);
classes
.
put
(
"java.lang."
+
className
,
result
);
}
}
if
(
result
==
null
)
{
return
null
;
}
classes
.
put
(
className
,
result
);
}
return
result
;
}
}
core/src/main/java/com/taobao/arthas/core/command/express/CustomClassResolver.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
import
ognl.ClassResolver
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
* @author diecui1202 on 2017/9/29.
* @see ognl.DefaultClassResolver
*/
public
class
CustomClassResolver
implements
ClassResolver
{
public
static
final
CustomClassResolver
customClassResolver
=
new
CustomClassResolver
();
private
Map
<
String
,
Class
<?>>
classes
=
new
ConcurrentHashMap
<
String
,
Class
<?>>(
101
);
private
CustomClassResolver
()
{
}
public
Class
<?>
classForName
(
String
className
,
Map
context
)
throws
ClassNotFoundException
{
Class
<?>
result
=
null
;
if
((
result
=
classes
.
get
(
className
))
==
null
)
{
try
{
ClassLoader
classLoader
=
Thread
.
currentThread
().
getContextClassLoader
();
if
(
classLoader
!=
null
)
{
result
=
classLoader
.
loadClass
(
className
);
}
else
{
result
=
Class
.
forName
(
className
);
}
}
catch
(
ClassNotFoundException
ex
)
{
if
(
className
.
indexOf
(
'.'
)
==
-
1
)
{
result
=
Class
.
forName
(
"java.lang."
+
className
);
classes
.
put
(
"java.lang."
+
className
,
result
);
}
}
classes
.
put
(
className
,
result
);
}
return
result
;
}
}
core/src/main/java/com/taobao/arthas/core/command/express/Express.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
/**
* 表达式
* Created by vlinux on 15/5/20.
*/
public
interface
Express
{
/**
* 根据表达式获取值
*
* @param express 表达式
* @return 表达式运算后的值
* @throws ExpressException 表达式运算出错
*/
Object
get
(
String
express
)
throws
ExpressException
;
/**
* 根据表达式判断是与否
*
* @param express 表达式
* @return 表达式运算后的布尔值
* @throws ExpressException 表达式运算出错
*/
boolean
is
(
String
express
)
throws
ExpressException
;
/**
* 绑定对象
*
* @param object 待绑定对象
* @return this
*/
Express
bind
(
Object
object
);
/**
* 绑定变量
*
* @param name 变量名
* @param value 变量值
* @return this
*/
Express
bind
(
String
name
,
Object
value
);
/**
* 重置整个表达式
*
* @return this
*/
Express
reset
();
}
core/src/main/java/com/taobao/arthas/core/command/express/ExpressException.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
/**
* 表达式异常
* Created by vlinux on 15/5/20.
*/
public
class
ExpressException
extends
Exception
{
private
final
String
express
;
/**
* 表达式异常
*
* @param express 原始表达式
* @param cause 异常原因
*/
public
ExpressException
(
String
express
,
Throwable
cause
)
{
super
(
cause
);
this
.
express
=
express
;
}
/**
* 获取表达式
*
* @return 返回出问题的表达式
*/
public
String
getExpress
()
{
return
express
;
}
}
core/src/main/java/com/taobao/arthas/core/command/express/ExpressFactory.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
/**
* ExpressFactory
* @author ralf0131 2017-01-04 14:40.
* @author hengyunabc 2018-10-08
*/
public
class
ExpressFactory
{
private
static
final
ThreadLocal
<
Express
>
expressRef
=
new
ThreadLocal
<
Express
>()
{
@Override
protected
Express
initialValue
()
{
return
new
OgnlExpress
();
}
};
/**
* get ThreadLocal Express Object
* @param object
* @return
*/
public
static
Express
threadLocalExpress
(
Object
object
)
{
return
expressRef
.
get
().
reset
().
bind
(
object
);
}
public
static
Express
unpooledExpress
(
ClassLoader
classloader
)
{
if
(
classloader
==
null
)
{
classloader
=
ClassLoader
.
getSystemClassLoader
();
}
return
new
OgnlExpress
(
new
ClassLoaderClassResolver
(
classloader
));
}
}
\ No newline at end of file
core/src/main/java/com/taobao/arthas/core/command/express/OgnlExpress.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.express
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
ognl.ClassResolver
;
import
ognl.DefaultMemberAccess
;
import
ognl.MemberAccess
;
import
ognl.Ognl
;
import
ognl.OgnlContext
;
import
ognl.OgnlRuntime
;
/**
* @author ralf0131 2017-01-04 14:41.
* @author hengyunabc 2018-10-18
*/
public
class
OgnlExpress
implements
Express
{
private
static
final
MemberAccess
MEMBER_ACCESS
=
new
DefaultMemberAccess
(
true
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
OgnlExpress
.
class
);
private
static
final
ArthasObjectPropertyAccessor
OBJECT_PROPERTY_ACCESSOR
=
new
ArthasObjectPropertyAccessor
();
private
Object
bindObject
;
private
final
OgnlContext
context
;
public
OgnlExpress
()
{
this
(
CustomClassResolver
.
customClassResolver
);
}
public
OgnlExpress
(
ClassResolver
classResolver
)
{
OgnlRuntime
.
setPropertyAccessor
(
Object
.
class
,
OBJECT_PROPERTY_ACCESSOR
);
context
=
new
OgnlContext
();
context
.
setClassResolver
(
classResolver
);
// allow private field access
context
.
setMemberAccess
(
MEMBER_ACCESS
);
}
@Override
public
Object
get
(
String
express
)
throws
ExpressException
{
try
{
return
Ognl
.
getValue
(
express
,
context
,
bindObject
);
}
catch
(
Exception
e
)
{
logger
.
error
(
"Error during evaluating the expression:"
,
e
);
throw
new
ExpressException
(
express
,
e
);
}
}
@Override
public
boolean
is
(
String
express
)
throws
ExpressException
{
final
Object
ret
=
get
(
express
);
return
ret
instanceof
Boolean
&&
(
Boolean
)
ret
;
}
@Override
public
Express
bind
(
Object
object
)
{
this
.
bindObject
=
object
;
return
this
;
}
@Override
public
Express
bind
(
String
name
,
Object
value
)
{
context
.
put
(
name
,
value
);
return
this
;
}
@Override
public
Express
reset
()
{
context
.
clear
();
context
.
setClassResolver
(
CustomClassResolver
.
customClassResolver
);
// allow private field access
context
.
setMemberAccess
(
MEMBER_ACCESS
);
return
this
;
}
}
core/src/main/java/com/taobao/arthas/core/command/hidden/JulyCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.hidden
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.middleware.cli.annotations.Hidden
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* @author vlinux on 02/11/2016.
*/
@Name
(
"july"
)
@Summary
(
"don't ask why"
)
@Hidden
public
class
JulyCommand
extends
AnnotatedCommand
{
@Override
public
void
process
(
CommandProcess
process
)
{
process
.
write
(
new
String
(
$$
())).
write
(
"\n"
).
end
();
}
private
static
byte
[]
$$
()
{
return
new
byte
[]{
0x49
,
0x20
,
0x77
,
0x69
,
0x6c
,
0x6c
,
0x20
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x6d
,
0x61
,
0x6b
,
0x65
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x61
,
0x6d
,
0x65
,
0x20
,
0x6d
,
0x69
,
0x73
,
0x74
,
0x61
,
0x6b
,
0x65
,
0x73
,
0x20
,
0x74
,
0x68
,
0x61
,
0x74
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x20
,
0x64
,
0x69
,
0x64
,
0x0a
,
0x49
,
0x20
,
0x77
,
0x69
,
0x6c
,
0x6c
,
0x20
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x6c
,
0x65
,
0x74
,
0x20
,
0x6d
,
0x79
,
0x73
,
0x65
,
0x6c
,
0x66
,
0x0a
,
0x43
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6d
,
0x79
,
0x20
,
0x68
,
0x65
,
0x61
,
0x72
,
0x74
,
0x20
,
0x73
,
0x6f
,
0x20
,
0x6d
,
0x75
,
0x63
,
0x68
,
0x20
,
0x6d
,
0x69
,
0x73
,
0x65
,
0x72
,
0x79
,
0x0a
,
0x49
,
0x20
,
0x77
,
0x69
,
0x6c
,
0x6c
,
0x20
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x62
,
0x72
,
0x65
,
0x61
,
0x6b
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x77
,
0x61
,
0x79
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x20
,
0x64
,
0x69
,
0x64
,
0x0a
,
0x59
,
0x6f
,
0x75
,
0x20
,
0x66
,
0x65
,
0x6c
,
0x6c
,
0x20
,
0x73
,
0x6f
,
0x20
,
0x68
,
0x61
,
0x72
,
0x64
,
0x0a
,
0x0a
,
0x49
,
0x20
,
0x76
,
0x65
,
0x20
,
0x6c
,
0x65
,
0x61
,
0x72
,
0x6e
,
0x65
,
0x64
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x68
,
0x61
,
0x72
,
0x64
,
0x20
,
0x77
,
0x61
,
0x79
,
0x0a
,
0x54
,
0x6f
,
0x20
,
0x6e
,
0x65
,
0x76
,
0x65
,
0x72
,
0x20
,
0x6c
,
0x65
,
0x74
,
0x20
,
0x69
,
0x74
,
0x20
,
0x67
,
0x65
,
0x74
,
0x20
,
0x74
,
0x68
,
0x61
,
0x74
,
0x20
,
0x66
,
0x61
,
0x72
,
0x0a
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6e
,
0x65
,
0x76
,
0x65
,
0x72
,
0x20
,
0x73
,
0x74
,
0x72
,
0x61
,
0x79
,
0x20
,
0x74
,
0x6f
,
0x6f
,
0x20
,
0x66
,
0x61
,
0x72
,
0x20
,
0x66
,
0x72
,
0x6f
,
0x6d
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x69
,
0x64
,
0x65
,
0x77
,
0x61
,
0x6c
,
0x6b
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6c
,
0x65
,
0x61
,
0x72
,
0x6e
,
0x65
,
0x64
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x70
,
0x6c
,
0x61
,
0x79
,
0x20
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x61
,
0x66
,
0x65
,
0x20
,
0x73
,
0x69
,
0x64
,
0x65
,
0x20
,
0x73
,
0x6f
,
0x20
,
0x49
,
0x20
,
0x64
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x20
,
0x67
,
0x65
,
0x74
,
0x20
,
0x68
,
0x75
,
0x72
,
0x74
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x66
,
0x69
,
0x6e
,
0x64
,
0x20
,
0x69
,
0x74
,
0x20
,
0x68
,
0x61
,
0x72
,
0x64
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x74
,
0x72
,
0x75
,
0x73
,
0x74
,
0x20
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x6f
,
0x6e
,
0x6c
,
0x79
,
0x20
,
0x6d
,
0x65
,
0x2c
,
0x20
,
0x62
,
0x75
,
0x74
,
0x20
,
0x65
,
0x76
,
0x65
,
0x72
,
0x79
,
0x6f
,
0x6e
,
0x65
,
0x20
,
0x61
,
0x72
,
0x6f
,
0x75
,
0x6e
,
0x64
,
0x20
,
0x6d
,
0x65
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x61
,
0x6d
,
0x20
,
0x61
,
0x66
,
0x72
,
0x61
,
0x69
,
0x64
,
0x0a
,
0x0a
,
0x49
,
0x20
,
0x6c
,
0x6f
,
0x73
,
0x65
,
0x20
,
0x6d
,
0x79
,
0x20
,
0x77
,
0x61
,
0x79
,
0x0a
,
0x41
,
0x6e
,
0x64
,
0x20
,
0x69
,
0x74
,
0x20
,
0x73
,
0x20
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x74
,
0x6f
,
0x6f
,
0x20
,
0x6c
,
0x6f
,
0x6e
,
0x67
,
0x20
,
0x62
,
0x65
,
0x66
,
0x6f
,
0x72
,
0x65
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x20
,
0x70
,
0x6f
,
0x69
,
0x6e
,
0x74
,
0x20
,
0x69
,
0x74
,
0x20
,
0x6f
,
0x75
,
0x74
,
0x0a
,
0x49
,
0x20
,
0x63
,
0x61
,
0x6e
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x63
,
0x72
,
0x79
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x20
,
0x6b
,
0x6e
,
0x6f
,
0x77
,
0x20
,
0x74
,
0x68
,
0x61
,
0x74
,
0x20
,
0x73
,
0x20
,
0x77
,
0x65
,
0x61
,
0x6b
,
0x6e
,
0x65
,
0x73
,
0x73
,
0x20
,
0x69
,
0x6e
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x72
,
0x20
,
0x65
,
0x79
,
0x65
,
0x73
,
0x0a
,
0x49
,
0x20
,
0x6d
,
0x20
,
0x66
,
0x6f
,
0x72
,
0x63
,
0x65
,
0x64
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x66
,
0x61
,
0x6b
,
0x65
,
0x0a
,
0x41
,
0x20
,
0x73
,
0x6d
,
0x69
,
0x6c
,
0x65
,
0x2c
,
0x20
,
0x61
,
0x20
,
0x6c
,
0x61
,
0x75
,
0x67
,
0x68
,
0x20
,
0x65
,
0x76
,
0x65
,
0x72
,
0x79
,
0x64
,
0x61
,
0x79
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x6d
,
0x79
,
0x20
,
0x6c
,
0x69
,
0x66
,
0x65
,
0x0a
,
0x4d
,
0x79
,
0x20
,
0x68
,
0x65
,
0x61
,
0x72
,
0x74
,
0x20
,
0x63
,
0x61
,
0x6e
,
0x27
,
0x74
,
0x20
,
0x70
,
0x6f
,
0x73
,
0x73
,
0x69
,
0x62
,
0x6c
,
0x79
,
0x20
,
0x62
,
0x72
,
0x65
,
0x61
,
0x6b
,
0x0a
,
0x57
,
0x68
,
0x65
,
0x6e
,
0x20
,
0x69
,
0x74
,
0x20
,
0x77
,
0x61
,
0x73
,
0x6e
,
0x27
,
0x74
,
0x20
,
0x65
,
0x76
,
0x65
,
0x6e
,
0x20
,
0x77
,
0x68
,
0x6f
,
0x6c
,
0x65
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x73
,
0x74
,
0x61
,
0x72
,
0x74
,
0x20
,
0x77
,
0x69
,
0x74
,
0x68
,
0x0a
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6e
,
0x65
,
0x76
,
0x65
,
0x72
,
0x20
,
0x73
,
0x74
,
0x72
,
0x61
,
0x79
,
0x20
,
0x74
,
0x6f
,
0x6f
,
0x20
,
0x66
,
0x61
,
0x72
,
0x20
,
0x66
,
0x72
,
0x6f
,
0x6d
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x69
,
0x64
,
0x65
,
0x77
,
0x61
,
0x6c
,
0x6b
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6c
,
0x65
,
0x61
,
0x72
,
0x6e
,
0x65
,
0x64
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x70
,
0x6c
,
0x61
,
0x79
,
0x20
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x61
,
0x66
,
0x65
,
0x20
,
0x73
,
0x69
,
0x64
,
0x65
,
0x20
,
0x73
,
0x6f
,
0x20
,
0x49
,
0x20
,
0x64
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x20
,
0x67
,
0x65
,
0x74
,
0x20
,
0x68
,
0x75
,
0x72
,
0x74
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x66
,
0x69
,
0x6e
,
0x64
,
0x20
,
0x69
,
0x74
,
0x20
,
0x68
,
0x61
,
0x72
,
0x64
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x74
,
0x72
,
0x75
,
0x73
,
0x74
,
0x20
,
0x6e
,
0x6f
,
0x74
,
0x20
,
0x6f
,
0x6e
,
0x6c
,
0x79
,
0x20
,
0x6d
,
0x65
,
0x2c
,
0x20
,
0x62
,
0x75
,
0x74
,
0x20
,
0x65
,
0x76
,
0x65
,
0x72
,
0x79
,
0x6f
,
0x6e
,
0x65
,
0x20
,
0x61
,
0x72
,
0x6f
,
0x75
,
0x6e
,
0x64
,
0x20
,
0x6d
,
0x65
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x61
,
0x6d
,
0x20
,
0x61
,
0x66
,
0x72
,
0x61
,
0x69
,
0x64
,
0x0a
,
0x0a
,
0x49
,
0x20
,
0x77
,
0x61
,
0x74
,
0x63
,
0x68
,
0x65
,
0x64
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x20
,
0x64
,
0x69
,
0x65
,
0x0a
,
0x49
,
0x20
,
0x68
,
0x65
,
0x61
,
0x72
,
0x64
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x20
,
0x63
,
0x72
,
0x79
,
0x20
,
0x65
,
0x76
,
0x65
,
0x72
,
0x79
,
0x20
,
0x6e
,
0x69
,
0x67
,
0x68
,
0x74
,
0x20
,
0x69
,
0x6e
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x72
,
0x20
,
0x73
,
0x6c
,
0x65
,
0x65
,
0x70
,
0x0a
,
0x49
,
0x20
,
0x77
,
0x61
,
0x73
,
0x20
,
0x73
,
0x6f
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x6e
,
0x67
,
0x0a
,
0x59
,
0x6f
,
0x75
,
0x20
,
0x73
,
0x68
,
0x6f
,
0x75
,
0x6c
,
0x64
,
0x20
,
0x68
,
0x61
,
0x76
,
0x65
,
0x20
,
0x6b
,
0x6e
,
0x6f
,
0x77
,
0x6e
,
0x20
,
0x62
,
0x65
,
0x74
,
0x74
,
0x65
,
0x72
,
0x20
,
0x74
,
0x68
,
0x61
,
0x6e
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x6c
,
0x65
,
0x61
,
0x6e
,
0x20
,
0x6f
,
0x6e
,
0x20
,
0x6d
,
0x65
,
0x0a
,
0x59
,
0x6f
,
0x75
,
0x20
,
0x6e
,
0x65
,
0x76
,
0x65
,
0x72
,
0x20
,
0x74
,
0x68
,
0x6f
,
0x75
,
0x67
,
0x68
,
0x74
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x61
,
0x6e
,
0x79
,
0x6f
,
0x6e
,
0x65
,
0x20
,
0x65
,
0x6c
,
0x73
,
0x65
,
0x0a
,
0x59
,
0x6f
,
0x75
,
0x20
,
0x6a
,
0x75
,
0x73
,
0x74
,
0x20
,
0x73
,
0x61
,
0x77
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x72
,
0x20
,
0x70
,
0x61
,
0x69
,
0x6e
,
0x0a
,
0x41
,
0x6e
,
0x64
,
0x20
,
0x6e
,
0x6f
,
0x77
,
0x20
,
0x49
,
0x20
,
0x63
,
0x72
,
0x79
,
0x20
,
0x69
,
0x6e
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x6d
,
0x69
,
0x64
,
0x64
,
0x6c
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x6e
,
0x69
,
0x67
,
0x68
,
0x74
,
0x0a
,
0x46
,
0x6f
,
0x72
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x61
,
0x6d
,
0x65
,
0x20
,
0x64
,
0x61
,
0x6d
,
0x6e
,
0x20
,
0x74
,
0x68
,
0x69
,
0x6e
,
0x67
,
0x0a
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6e
,
0x65
,
0x76
,
0x65
,
0x72
,
0x20
,
0x73
,
0x74
,
0x72
,
0x61
,
0x79
,
0x20
,
0x74
,
0x6f
,
0x6f
,
0x20
,
0x66
,
0x61
,
0x72
,
0x20
,
0x66
,
0x72
,
0x6f
,
0x6d
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x69
,
0x64
,
0x65
,
0x77
,
0x61
,
0x6c
,
0x6b
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6c
,
0x65
,
0x61
,
0x72
,
0x6e
,
0x65
,
0x64
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x70
,
0x6c
,
0x61
,
0x79
,
0x20
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x68
,
0x65
,
0x20
,
0x73
,
0x61
,
0x66
,
0x65
,
0x20
,
0x73
,
0x69
,
0x64
,
0x65
,
0x20
,
0x73
,
0x6f
,
0x20
,
0x49
,
0x20
,
0x64
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x20
,
0x67
,
0x65
,
0x74
,
0x20
,
0x68
,
0x75
,
0x72
,
0x74
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x74
,
0x72
,
0x79
,
0x20
,
0x6d
,
0x79
,
0x20
,
0x68
,
0x61
,
0x72
,
0x64
,
0x65
,
0x73
,
0x74
,
0x20
,
0x6a
,
0x75
,
0x73
,
0x74
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x66
,
0x6f
,
0x72
,
0x67
,
0x65
,
0x74
,
0x20
,
0x65
,
0x76
,
0x65
,
0x72
,
0x79
,
0x74
,
0x68
,
0x69
,
0x6e
,
0x67
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x64
,
0x6f
,
0x6e
,
0x20
,
0x74
,
0x20
,
0x6b
,
0x6e
,
0x6f
,
0x77
,
0x20
,
0x68
,
0x6f
,
0x77
,
0x20
,
0x74
,
0x6f
,
0x20
,
0x6c
,
0x65
,
0x74
,
0x20
,
0x61
,
0x6e
,
0x79
,
0x6f
,
0x6e
,
0x65
,
0x20
,
0x65
,
0x6c
,
0x73
,
0x65
,
0x20
,
0x69
,
0x6e
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x6d
,
0x20
,
0x61
,
0x73
,
0x68
,
0x61
,
0x6d
,
0x65
,
0x64
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x6d
,
0x79
,
0x20
,
0x6c
,
0x69
,
0x66
,
0x65
,
0x20
,
0x62
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x69
,
0x74
,
0x20
,
0x73
,
0x20
,
0x65
,
0x6d
,
0x70
,
0x74
,
0x79
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x49
,
0x20
,
0x61
,
0x6d
,
0x20
,
0x61
,
0x66
,
0x72
,
0x61
,
0x69
,
0x64
,
0x0a
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x42
,
0x65
,
0x63
,
0x61
,
0x75
,
0x73
,
0x65
,
0x20
,
0x6f
,
0x66
,
0x20
,
0x79
,
0x6f
,
0x75
,
0x0a
,
0x2e
,
0x2e
,
0x2e
,
0x0a
,
/*0x0a, 0x66, 0x6f, 0x72, 0x20, 0x6a, 0x75, 0x6c, 0x79, 0x0a, 0x0a,*/
};
}
}
core/src/main/java/com/taobao/arthas/core/command/hidden/ThanksCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.hidden
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ArthasBanner
;
import
com.taobao.middleware.cli.annotations.Hidden
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Summary
;
/**
* 工具介绍<br/>
* 感谢
*
* @author vlinux on 15/9/1.
*/
@Name
(
"thanks"
)
@Summary
(
"Credits to all personnel and organization who either contribute or help to this product. Thanks you all!"
)
@Hidden
public
class
ThanksCommand
extends
AnnotatedCommand
{
@Override
public
void
process
(
CommandProcess
process
)
{
process
.
write
(
ArthasBanner
.
credit
()).
write
(
"\n"
).
end
();
}
}
core/src/main/java/com/taobao/arthas/core/command/klass100/ClassDumpTransformer.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.klass100
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.taobao.arthas.core.util.FileUtils
;
import
com.taobao.arthas.core.util.LogUtil
;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.instrument.ClassFileTransformer
;
import
java.lang.instrument.IllegalClassFormatException
;
import
java.security.ProtectionDomain
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author beiwei30 on 25/11/2016.
*/
class
ClassDumpTransformer
implements
ClassFileTransformer
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ClassDumpTransformer
.
class
);
private
Set
<
Class
<?>>
classesToEnhance
;
private
Map
<
Class
<?>,
File
>
dumpResult
;
private
File
arthasLogHome
;
private
File
directory
;
public
ClassDumpTransformer
(
Set
<
Class
<?>>
classesToEnhance
)
{
this
(
classesToEnhance
,
null
);
}
public
ClassDumpTransformer
(
Set
<
Class
<?>>
classesToEnhance
,
File
directory
)
{
this
.
classesToEnhance
=
classesToEnhance
;
this
.
dumpResult
=
new
HashMap
<
Class
<?>,
File
>();
this
.
arthasLogHome
=
new
File
(
LogUtil
.
loggingDir
());
this
.
directory
=
directory
;
}
@Override
public
byte
[]
transform
(
ClassLoader
loader
,
String
className
,
Class
<?>
classBeingRedefined
,
ProtectionDomain
protectionDomain
,
byte
[]
classfileBuffer
)
throws
IllegalClassFormatException
{
if
(
classesToEnhance
.
contains
(
classBeingRedefined
))
{
dumpClassIfNecessary
(
classBeingRedefined
,
classfileBuffer
);
}
return
null
;
}
public
Map
<
Class
<?>,
File
>
getDumpResult
()
{
return
dumpResult
;
}
private
void
dumpClassIfNecessary
(
Class
<?>
clazz
,
byte
[]
data
)
{
String
className
=
clazz
.
getName
();
ClassLoader
classLoader
=
clazz
.
getClassLoader
();
String
classDumpDir
=
"classdump"
;
// 创建类所在的包路径
File
dumpDir
=
null
;
if
(
directory
!=
null
)
{
dumpDir
=
directory
;
}
else
{
dumpDir
=
new
File
(
arthasLogHome
,
classDumpDir
);
}
if
(!
dumpDir
.
mkdirs
()
&&
!
dumpDir
.
exists
())
{
logger
.
warn
(
"create dump directory:{} failed."
,
dumpDir
.
getAbsolutePath
());
return
;
}
String
fileName
;
if
(
classLoader
!=
null
)
{
fileName
=
classLoader
.
getClass
().
getName
()
+
"-"
+
Integer
.
toHexString
(
classLoader
.
hashCode
())
+
File
.
separator
+
className
.
replace
(
"."
,
File
.
separator
)
+
".class"
;
}
else
{
fileName
=
className
.
replace
(
"."
,
File
.
separator
)
+
".class"
;
}
File
dumpClassFile
=
new
File
(
dumpDir
,
fileName
);
// 将类字节码写入文件
try
{
FileUtils
.
writeByteArrayToFile
(
dumpClassFile
,
data
);
dumpResult
.
put
(
clazz
,
dumpClassFile
);
}
catch
(
IOException
e
)
{
logger
.
warn
(
"dump class:{} to file {} failed."
,
className
,
dumpClassFile
,
e
);
}
}
}
core/src/main/java/com/taobao/arthas/core/command/klass100/ClassLoaderCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.klass100
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.model.ClassDetailVO
;
import
com.taobao.arthas.core.command.model.ClassLoaderModel
;
import
com.taobao.arthas.core.command.model.ClassLoaderVO
;
import
com.taobao.arthas.core.command.model.ClassSetVO
;
import
com.taobao.arthas.core.command.model.MessageModel
;
import
com.taobao.arthas.core.command.model.RowAffectModel
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.shell.handlers.Handler
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.arthas.core.util.ClassLoaderUtils
;
import
com.taobao.arthas.core.util.ResultUtils
;
import
com.taobao.arthas.core.util.affect.RowAffect
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Option
;
import
com.taobao.middleware.cli.annotations.Summary
;
import
java.lang.instrument.Instrumentation
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.security.CodeSource
;
import
java.security.ProtectionDomain
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.Enumeration
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Set
;
import
java.util.SortedSet
;
import
java.util.TreeMap
;
import
java.util.TreeSet
;
@Name
(
"classloader"
)
@Summary
(
"Show classloader info"
)
@Description
(
Constants
.
EXAMPLE
+
" classloader\n"
+
" classloader -t\n"
+
" classloader -l\n"
+
" classloader -c 327a647b\n"
+
" classloader -c 327a647b -r META-INF/MANIFEST.MF\n"
+
" classloader -a\n"
+
" classloader -a -c 327a647b\n"
+
" classloader -c 659e0bfd --load demo.MathGame\n"
+
" classloader -u # url statistics\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"classloader"
)
public
class
ClassLoaderCommand
extends
AnnotatedCommand
{
private
Logger
logger
=
LoggerFactory
.
getLogger
(
ClassLoaderCommand
.
class
);
private
boolean
isTree
=
false
;
private
String
hashCode
;
private
String
classLoaderClass
;
private
boolean
all
=
false
;
private
String
resource
;
private
boolean
includeReflectionClassLoader
=
true
;
private
boolean
listClassLoader
=
false
;
private
boolean
urlStat
=
false
;
private
String
loadClass
=
null
;
private
volatile
boolean
isInterrupted
=
false
;
@Option
(
shortName
=
"t"
,
longName
=
"tree"
,
flag
=
true
)
@Description
(
"Display ClassLoader tree"
)
public
void
setTree
(
boolean
tree
)
{
isTree
=
tree
;
}
@Option
(
longName
=
"classLoaderClass"
)
@Description
(
"The class name of the special class's classLoader."
)
public
void
setClassLoaderClass
(
String
classLoaderClass
)
{
this
.
classLoaderClass
=
classLoaderClass
;
}
@Option
(
shortName
=
"c"
,
longName
=
"classloader"
)
@Description
(
"The hash code of the special ClassLoader"
)
public
void
setHashCode
(
String
hashCode
)
{
this
.
hashCode
=
hashCode
;
}
@Option
(
shortName
=
"a"
,
longName
=
"all"
,
flag
=
true
)
@Description
(
"Display all classes loaded by ClassLoader"
)
public
void
setAll
(
boolean
all
)
{
this
.
all
=
all
;
}
@Option
(
shortName
=
"r"
,
longName
=
"resource"
)
@Description
(
"Use ClassLoader to find resources, won't work without -c specified"
)
public
void
setResource
(
String
resource
)
{
this
.
resource
=
resource
;
}
@Option
(
shortName
=
"i"
,
longName
=
"include-reflection-classloader"
,
flag
=
true
)
@Description
(
"Include sun.reflect.DelegatingClassLoader"
)
public
void
setIncludeReflectionClassLoader
(
boolean
includeReflectionClassLoader
)
{
this
.
includeReflectionClassLoader
=
includeReflectionClassLoader
;
}
@Option
(
shortName
=
"l"
,
longName
=
"list-classloader"
,
flag
=
true
)
@Description
(
"Display statistics info by classloader instance"
)
public
void
setListClassLoader
(
boolean
listClassLoader
)
{
this
.
listClassLoader
=
listClassLoader
;
}
@Option
(
longName
=
"load"
)
@Description
(
"Use ClassLoader to load class, won't work without -c specified"
)
public
void
setLoadClass
(
String
className
)
{
this
.
loadClass
=
className
;
}
@Option
(
shortName
=
"u"
,
longName
=
"url-stat"
,
flag
=
true
)
@Description
(
"Display classloader url statistics"
)
public
void
setUrlStat
(
boolean
urlStat
)
{
this
.
urlStat
=
urlStat
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
// ctrl-C support
process
.
interruptHandler
(
new
ClassLoaderInterruptHandler
(
this
));
ClassLoader
targetClassLoader
=
null
;
boolean
classLoaderSpecified
=
false
;
Instrumentation
inst
=
process
.
session
().
getInstrumentation
();
if
(
urlStat
)
{
Map
<
ClassLoaderVO
,
ClassLoaderUrlStat
>
urlStats
=
this
.
urlStats
(
inst
);
ClassLoaderModel
model
=
new
ClassLoaderModel
();
model
.
setUrlStats
(
urlStats
);
process
.
appendResult
(
model
);
process
.
end
();
return
;
}
if
(
hashCode
!=
null
||
classLoaderClass
!=
null
)
{
classLoaderSpecified
=
true
;
}
if
(
hashCode
!=
null
)
{
Set
<
ClassLoader
>
allClassLoader
=
getAllClassLoaders
(
inst
);
for
(
ClassLoader
cl
:
allClassLoader
)
{
if
(
Integer
.
toHexString
(
cl
.
hashCode
()).
equals
(
hashCode
))
{
targetClassLoader
=
cl
;
break
;
}
}
}
else
if
(
classLoaderClass
!=
null
)
{
List
<
ClassLoader
>
matchedClassLoaders
=
ClassLoaderUtils
.
getClassLoaderByClassName
(
inst
,
classLoaderClass
);
if
(
matchedClassLoaders
.
size
()
==
1
)
{
targetClassLoader
=
matchedClassLoaders
.
get
(
0
);
}
else
if
(
matchedClassLoaders
.
size
()
>
1
)
{
Collection
<
ClassLoaderVO
>
classLoaderVOList
=
ClassUtils
.
createClassLoaderVOList
(
matchedClassLoaders
);
ClassLoaderModel
classloaderModel
=
new
ClassLoaderModel
()
.
setClassLoaderClass
(
classLoaderClass
)
.
setMatchedClassLoaders
(
classLoaderVOList
);
process
.
appendResult
(
classloaderModel
);
process
.
end
(-
1
,
"Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'"
);
return
;
}
else
{
process
.
end
(-
1
,
"Can not find classloader by class name: "
+
classLoaderClass
+
"."
);
return
;
}
}
if
(
all
)
{
processAllClasses
(
process
,
inst
);
}
else
if
(
classLoaderSpecified
&&
resource
!=
null
)
{
processResources
(
process
,
inst
,
targetClassLoader
);
}
else
if
(
classLoaderSpecified
&&
this
.
loadClass
!=
null
)
{
processLoadClass
(
process
,
inst
,
targetClassLoader
);
}
else
if
(
classLoaderSpecified
)
{
processClassLoader
(
process
,
inst
,
targetClassLoader
);
}
else
if
(
listClassLoader
||
isTree
){
processClassLoaders
(
process
,
inst
);
}
else
{
processClassLoaderStats
(
process
,
inst
);
}
}
/**
* Calculate classloader statistics.
* e.g. In JVM, there are 100 GrooyClassLoader instances, which loaded 200 classes in total
* @param process
* @param inst
*/
private
void
processClassLoaderStats
(
CommandProcess
process
,
Instrumentation
inst
)
{
RowAffect
affect
=
new
RowAffect
();
List
<
ClassLoaderInfo
>
classLoaderInfos
=
getAllClassLoaderInfo
(
inst
);
Map
<
String
,
ClassLoaderStat
>
classLoaderStats
=
new
HashMap
<
String
,
ClassLoaderStat
>();
for
(
ClassLoaderInfo
info:
classLoaderInfos
)
{
String
name
=
info
.
classLoader
==
null
?
"BootstrapClassLoader"
:
info
.
classLoader
.
getClass
().
getName
();
ClassLoaderStat
stat
=
classLoaderStats
.
get
(
name
);
if
(
null
==
stat
)
{
stat
=
new
ClassLoaderStat
();
classLoaderStats
.
put
(
name
,
stat
);
}
stat
.
addLoadedCount
(
info
.
loadedClassCount
);
stat
.
addNumberOfInstance
(
1
);
}
// sort the map by value
TreeMap
<
String
,
ClassLoaderStat
>
sorted
=
new
TreeMap
<
String
,
ClassLoaderStat
>(
new
ValueComparator
(
classLoaderStats
));
sorted
.
putAll
(
classLoaderStats
);
process
.
appendResult
(
new
ClassLoaderModel
().
setClassLoaderStats
(
sorted
));
affect
.
rCnt
(
sorted
.
keySet
().
size
());
process
.
appendResult
(
new
RowAffectModel
(
affect
));
process
.
end
();
}
private
void
processClassLoaders
(
CommandProcess
process
,
Instrumentation
inst
)
{
RowAffect
affect
=
new
RowAffect
();
List
<
ClassLoaderInfo
>
classLoaderInfos
=
includeReflectionClassLoader
?
getAllClassLoaderInfo
(
inst
)
:
getAllClassLoaderInfo
(
inst
,
new
SunReflectionClassLoaderFilter
());
List
<
ClassLoaderVO
>
classLoaderVOs
=
new
ArrayList
<
ClassLoaderVO
>(
classLoaderInfos
.
size
());
for
(
ClassLoaderInfo
classLoaderInfo
:
classLoaderInfos
)
{
ClassLoaderVO
classLoaderVO
=
ClassUtils
.
createClassLoaderVO
(
classLoaderInfo
.
classLoader
);
classLoaderVO
.
setLoadedCount
(
classLoaderInfo
.
loadedClassCount
());
classLoaderVOs
.
add
(
classLoaderVO
);
}
if
(
isTree
){
classLoaderVOs
=
processClassLoaderTree
(
classLoaderVOs
);
}
process
.
appendResult
(
new
ClassLoaderModel
().
setClassLoaders
(
classLoaderVOs
).
setTree
(
isTree
));
affect
.
rCnt
(
classLoaderInfos
.
size
());
process
.
appendResult
(
new
RowAffectModel
(
affect
));
process
.
end
();
}
// 根据 ClassLoader 来打印URLClassLoader的urls
private
void
processClassLoader
(
CommandProcess
process
,
Instrumentation
inst
,
ClassLoader
targetClassLoader
)
{
RowAffect
affect
=
new
RowAffect
();
if
(
targetClassLoader
!=
null
)
{
if
(
targetClassLoader
instanceof
URLClassLoader
)
{
List
<
String
>
classLoaderUrls
=
getClassLoaderUrls
(
targetClassLoader
);
affect
.
rCnt
(
classLoaderUrls
.
size
());
if
(
classLoaderUrls
.
isEmpty
())
{
process
.
appendResult
(
new
MessageModel
(
"urls is empty."
));
}
else
{
process
.
appendResult
(
new
ClassLoaderModel
().
setUrls
(
classLoaderUrls
));
affect
.
rCnt
(
classLoaderUrls
.
size
());
}
}
else
{
process
.
appendResult
(
new
MessageModel
(
"not a URLClassLoader."
));
}
}
process
.
appendResult
(
new
RowAffectModel
(
affect
));
process
.
end
();
}
// 使用ClassLoader去getResources
private
void
processResources
(
CommandProcess
process
,
Instrumentation
inst
,
ClassLoader
targetClassLoader
)
{
RowAffect
affect
=
new
RowAffect
();
int
rowCount
=
0
;
List
<
String
>
resources
=
new
ArrayList
<
String
>();
if
(
targetClassLoader
!=
null
)
{
try
{
Enumeration
<
URL
>
urls
=
targetClassLoader
.
getResources
(
resource
);
while
(
urls
.
hasMoreElements
())
{
URL
url
=
urls
.
nextElement
();
resources
.
add
(
url
.
toString
());
rowCount
++;
}
}
catch
(
Throwable
e
)
{
logger
.
warn
(
"get resource failed, resource: {}"
,
resource
,
e
);
}
}
affect
.
rCnt
(
rowCount
);
process
.
appendResult
(
new
ClassLoaderModel
().
setResources
(
resources
));
process
.
appendResult
(
new
RowAffectModel
(
affect
));
process
.
end
();
}
// Use ClassLoader to loadClass
private
void
processLoadClass
(
CommandProcess
process
,
Instrumentation
inst
,
ClassLoader
targetClassLoader
)
{
if
(
targetClassLoader
!=
null
)
{
try
{
Class
<?>
clazz
=
targetClassLoader
.
loadClass
(
this
.
loadClass
);
process
.
appendResult
(
new
MessageModel
(
"load class success."
));
ClassDetailVO
classInfo
=
ClassUtils
.
createClassInfo
(
clazz
,
false
,
null
);
process
.
appendResult
(
new
ClassLoaderModel
().
setLoadClass
(
classInfo
));
}
catch
(
Throwable
e
)
{
logger
.
warn
(
"load class error, class: {}"
,
this
.
loadClass
,
e
);
process
.
end
(-
1
,
"load class error, class: "
+
this
.
loadClass
+
", error: "
+
e
.
toString
());
return
;
}
}
process
.
end
();
}
private
void
processAllClasses
(
CommandProcess
process
,
Instrumentation
inst
)
{
RowAffect
affect
=
new
RowAffect
();
getAllClasses
(
hashCode
,
inst
,
affect
,
process
);
if
(
checkInterrupted
(
process
))
{
return
;
}
process
.
appendResult
(
new
RowAffectModel
(
affect
));
process
.
end
();
}
/**
* 获取到所有的class, 还有它们的classloader,按classloader归类好,统一输出每个classloader里有哪些class
* <p>
* 当hashCode是null,则把所有的classloader的都打印
*
*/
@SuppressWarnings
(
"rawtypes"
)
private
void
getAllClasses
(
String
hashCode
,
Instrumentation
inst
,
RowAffect
affect
,
CommandProcess
process
)
{
int
hashCodeInt
=
-
1
;
if
(
hashCode
!=
null
)
{
hashCodeInt
=
Integer
.
valueOf
(
hashCode
,
16
);
}
SortedSet
<
Class
<?>>
bootstrapClassSet
=
new
TreeSet
<
Class
<?>>(
new
Comparator
<
Class
>()
{
@Override
public
int
compare
(
Class
o1
,
Class
o2
)
{
return
o1
.
getName
().
compareTo
(
o2
.
getName
());
}
});
Class
[]
allLoadedClasses
=
inst
.
getAllLoadedClasses
();
Map
<
ClassLoader
,
SortedSet
<
Class
<?>>>
classLoaderClassMap
=
new
HashMap
<
ClassLoader
,
SortedSet
<
Class
<?>>>();
for
(
Class
clazz
:
allLoadedClasses
)
{
ClassLoader
classLoader
=
clazz
.
getClassLoader
();
// Class loaded by BootstrapClassLoader
if
(
classLoader
==
null
)
{
if
(
hashCode
==
null
)
{
bootstrapClassSet
.
add
(
clazz
);
}
continue
;
}
if
(
hashCode
!=
null
&&
classLoader
.
hashCode
()
!=
hashCodeInt
)
{
continue
;
}
SortedSet
<
Class
<?>>
classSet
=
classLoaderClassMap
.
get
(
classLoader
);
if
(
classSet
==
null
)
{
classSet
=
new
TreeSet
<
Class
<?>>(
new
Comparator
<
Class
<?>>()
{
@Override
public
int
compare
(
Class
<?>
o1
,
Class
<?>
o2
)
{
return
o1
.
getName
().
compareTo
(
o2
.
getName
());
}
});
classLoaderClassMap
.
put
(
classLoader
,
classSet
);
}
classSet
.
add
(
clazz
);
}
// output bootstrapClassSet
int
pageSize
=
256
;
processClassSet
(
process
,
ClassUtils
.
createClassLoaderVO
(
null
),
bootstrapClassSet
,
pageSize
,
affect
);
// output other classSet
for
(
Entry
<
ClassLoader
,
SortedSet
<
Class
<?>>>
entry
:
classLoaderClassMap
.
entrySet
())
{
if
(
checkInterrupted
(
process
))
{
return
;
}
ClassLoader
classLoader
=
entry
.
getKey
();
SortedSet
<
Class
<?>>
classSet
=
entry
.
getValue
();
processClassSet
(
process
,
ClassUtils
.
createClassLoaderVO
(
classLoader
),
classSet
,
pageSize
,
affect
);
}
}
private
void
processClassSet
(
final
CommandProcess
process
,
final
ClassLoaderVO
classLoaderVO
,
Collection
<
Class
<?>>
classes
,
int
pageSize
,
final
RowAffect
affect
)
{
//分批输出classNames, Ctrl+C可以中断执行
ResultUtils
.
processClassNames
(
classes
,
pageSize
,
new
ResultUtils
.
PaginationHandler
<
List
<
String
>>()
{
@Override
public
boolean
handle
(
List
<
String
>
classNames
,
int
segment
)
{
process
.
appendResult
(
new
ClassLoaderModel
().
setClassSet
(
new
ClassSetVO
(
classLoaderVO
,
classNames
,
segment
)));
affect
.
rCnt
(
classNames
.
size
());
return
!
checkInterrupted
(
process
);
}
});
}
private
boolean
checkInterrupted
(
CommandProcess
process
)
{
if
(!
process
.
isRunning
())
{
return
true
;
}
if
(
isInterrupted
){
process
.
end
(-
1
,
"Processing has been interrupted"
);
return
true
;
}
else
{
return
false
;
}
}
private
static
List
<
String
>
getClassLoaderUrls
(
ClassLoader
classLoader
)
{
List
<
String
>
urlStrs
=
new
ArrayList
<
String
>();
if
(
classLoader
instanceof
URLClassLoader
)
{
URLClassLoader
cl
=
(
URLClassLoader
)
classLoader
;
URL
[]
urls
=
cl
.
getURLs
();
if
(
urls
!=
null
)
{
for
(
URL
url
:
urls
)
{
urlStrs
.
add
(
url
.
toString
());
}
}
}
return
urlStrs
;
}
private
Map
<
ClassLoaderVO
,
ClassLoaderUrlStat
>
urlStats
(
Instrumentation
inst
)
{
Map
<
ClassLoaderVO
,
ClassLoaderUrlStat
>
urlStats
=
new
HashMap
<
ClassLoaderVO
,
ClassLoaderUrlStat
>();
Map
<
ClassLoader
,
Set
<
String
>>
usedUrlsMap
=
new
HashMap
<
ClassLoader
,
Set
<
String
>>();
for
(
Class
<?>
clazz
:
inst
.
getAllLoadedClasses
())
{
ClassLoader
classLoader
=
clazz
.
getClassLoader
();
if
(
classLoader
!=
null
)
{
ProtectionDomain
protectionDomain
=
clazz
.
getProtectionDomain
();
CodeSource
codeSource
=
protectionDomain
.
getCodeSource
();
if
(
codeSource
!=
null
)
{
URL
location
=
codeSource
.
getLocation
();
if
(
location
!=
null
)
{
Set
<
String
>
urls
=
usedUrlsMap
.
get
(
classLoader
);
if
(
urls
==
null
)
{
urls
=
new
HashSet
<
String
>();
usedUrlsMap
.
put
(
classLoader
,
urls
);
}
urls
.
add
(
location
.
toString
());
}
}
}
}
for
(
Entry
<
ClassLoader
,
Set
<
String
>>
entry
:
usedUrlsMap
.
entrySet
())
{
ClassLoader
loader
=
entry
.
getKey
();
Set
<
String
>
usedUrls
=
entry
.
getValue
();
List
<
String
>
allUrls
=
getClassLoaderUrls
(
loader
);
List
<
String
>
unusedUrls
=
new
ArrayList
<
String
>();
for
(
String
url
:
allUrls
)
{
if
(!
usedUrls
.
contains
(
url
))
{
unusedUrls
.
add
(
url
);
}
}
urlStats
.
put
(
ClassUtils
.
createClassLoaderVO
(
loader
),
new
ClassLoaderUrlStat
(
usedUrls
,
unusedUrls
));
}
return
urlStats
;
}
// 以树状列出ClassLoader的继承结构
private
static
List
<
ClassLoaderVO
>
processClassLoaderTree
(
List
<
ClassLoaderVO
>
classLoaders
)
{
List
<
ClassLoaderVO
>
rootClassLoaders
=
new
ArrayList
<
ClassLoaderVO
>();
List
<
ClassLoaderVO
>
parentNotNullClassLoaders
=
new
ArrayList
<
ClassLoaderVO
>();
for
(
ClassLoaderVO
classLoaderVO
:
classLoaders
)
{
if
(
classLoaderVO
.
getParent
()
==
null
)
{
rootClassLoaders
.
add
(
classLoaderVO
);
}
else
{
parentNotNullClassLoaders
.
add
(
classLoaderVO
);
}
}
for
(
ClassLoaderVO
classLoaderVO
:
rootClassLoaders
)
{
buildTree
(
classLoaderVO
,
parentNotNullClassLoaders
);
}
return
rootClassLoaders
;
}
private
static
void
buildTree
(
ClassLoaderVO
parent
,
List
<
ClassLoaderVO
>
parentNotNullClassLoaders
)
{
for
(
ClassLoaderVO
classLoaderVO
:
parentNotNullClassLoaders
)
{
if
(
parent
.
getName
().
equals
(
classLoaderVO
.
getParent
())){
parent
.
addChild
(
classLoaderVO
);
buildTree
(
classLoaderVO
,
parentNotNullClassLoaders
);
}
}
}
private
static
Set
<
ClassLoader
>
getAllClassLoaders
(
Instrumentation
inst
,
Filter
...
filters
)
{
Set
<
ClassLoader
>
classLoaderSet
=
new
HashSet
<
ClassLoader
>();
for
(
Class
<?>
clazz
:
inst
.
getAllLoadedClasses
())
{
ClassLoader
classLoader
=
clazz
.
getClassLoader
();
if
(
classLoader
!=
null
)
{
if
(
shouldInclude
(
classLoader
,
filters
))
{
classLoaderSet
.
add
(
classLoader
);
}
}
}
return
classLoaderSet
;
}
private
static
List
<
ClassLoaderInfo
>
getAllClassLoaderInfo
(
Instrumentation
inst
,
Filter
...
filters
)
{
// 这里认为class.getClassLoader()返回是null的是由BootstrapClassLoader加载的,特殊处理
ClassLoaderInfo
bootstrapInfo
=
new
ClassLoaderInfo
(
null
);
Map
<
ClassLoader
,
ClassLoaderInfo
>
loaderInfos
=
new
HashMap
<
ClassLoader
,
ClassLoaderInfo
>();
for
(
Class
<?>
clazz
:
inst
.
getAllLoadedClasses
())
{
ClassLoader
classLoader
=
clazz
.
getClassLoader
();
if
(
classLoader
==
null
)
{
bootstrapInfo
.
increase
();
}
else
{
if
(
shouldInclude
(
classLoader
,
filters
))
{
ClassLoaderInfo
loaderInfo
=
loaderInfos
.
get
(
classLoader
);
if
(
loaderInfo
==
null
)
{
loaderInfo
=
new
ClassLoaderInfo
(
classLoader
);
loaderInfos
.
put
(
classLoader
,
loaderInfo
);
ClassLoader
parent
=
classLoader
.
getParent
();
while
(
parent
!=
null
)
{
ClassLoaderInfo
parentLoaderInfo
=
loaderInfos
.
get
(
parent
);
if
(
parentLoaderInfo
==
null
)
{
parentLoaderInfo
=
new
ClassLoaderInfo
(
parent
);
loaderInfos
.
put
(
parent
,
parentLoaderInfo
);
}
parent
=
parent
.
getParent
();
}
}
loaderInfo
.
increase
();
}
}
}
// 排序时,把用户自己定的ClassLoader排在最前面,以sun.
// 开头的放后面,因为sun.reflect.DelegatingClassLoader的实例太多
List
<
ClassLoaderInfo
>
sunClassLoaderList
=
new
ArrayList
<
ClassLoaderInfo
>();
List
<
ClassLoaderInfo
>
otherClassLoaderList
=
new
ArrayList
<
ClassLoaderInfo
>();
for
(
Entry
<
ClassLoader
,
ClassLoaderInfo
>
entry
:
loaderInfos
.
entrySet
())
{
ClassLoader
classLoader
=
entry
.
getKey
();
if
(
classLoader
.
getClass
().
getName
().
startsWith
(
"sun."
))
{
sunClassLoaderList
.
add
(
entry
.
getValue
());
}
else
{
otherClassLoaderList
.
add
(
entry
.
getValue
());
}
}
Collections
.
sort
(
sunClassLoaderList
);
Collections
.
sort
(
otherClassLoaderList
);
List
<
ClassLoaderInfo
>
result
=
new
ArrayList
<
ClassLoaderInfo
>();
result
.
add
(
bootstrapInfo
);
result
.
addAll
(
otherClassLoaderList
);
result
.
addAll
(
sunClassLoaderList
);
return
result
;
}
private
static
boolean
shouldInclude
(
ClassLoader
classLoader
,
Filter
...
filters
)
{
if
(
filters
==
null
)
{
return
true
;
}
for
(
Filter
filter
:
filters
)
{
if
(!
filter
.
accept
(
classLoader
))
{
return
false
;
}
}
return
true
;
}
private
static
class
ClassLoaderInfo
implements
Comparable
<
ClassLoaderInfo
>
{
private
ClassLoader
classLoader
;
private
int
loadedClassCount
=
0
;
ClassLoaderInfo
(
ClassLoader
classLoader
)
{
this
.
classLoader
=
classLoader
;
}
public
String
getName
()
{
if
(
classLoader
!=
null
)
{
return
classLoader
.
toString
();
}
return
"BootstrapClassLoader"
;
}
String
hashCodeStr
()
{
if
(
classLoader
!=
null
)
{
return
""
+
Integer
.
toHexString
(
classLoader
.
hashCode
());
}
return
"null"
;
}
void
increase
()
{
loadedClassCount
++;
}
int
loadedClassCount
()
{
return
loadedClassCount
;
}
ClassLoader
parent
()
{
return
classLoader
==
null
?
null
:
classLoader
.
getParent
();
}
String
parentStr
()
{
if
(
classLoader
==
null
)
{
return
"null"
;
}
ClassLoader
parent
=
classLoader
.
getParent
();
if
(
parent
==
null
)
{
return
"null"
;
}
return
parent
.
toString
();
}
@Override
public
int
compareTo
(
ClassLoaderInfo
other
)
{
if
(
other
==
null
)
{
return
-
1
;
}
if
(
other
.
classLoader
==
null
)
{
return
-
1
;
}
if
(
this
.
classLoader
==
null
)
{
return
-
1
;
}
return
this
.
classLoader
.
getClass
().
getName
().
compareTo
(
other
.
classLoader
.
getClass
().
getName
());
}
}
private
interface
Filter
{
boolean
accept
(
ClassLoader
classLoader
);
}
private
static
class
SunReflectionClassLoaderFilter
implements
Filter
{
private
static
final
List
<
String
>
REFLECTION_CLASSLOADERS
=
Arrays
.
asList
(
"sun.reflect.DelegatingClassLoader"
,
"jdk.internal.reflect.DelegatingClassLoader"
);
@Override
public
boolean
accept
(
ClassLoader
classLoader
)
{
return
!
REFLECTION_CLASSLOADERS
.
contains
(
classLoader
.
getClass
().
getName
());
}
}
public
static
class
ClassLoaderUrlStat
{
private
Collection
<
String
>
usedUrls
;
private
Collection
<
String
>
unUsedUrls
;
public
ClassLoaderUrlStat
()
{
}
public
ClassLoaderUrlStat
(
Collection
<
String
>
usedUrls
,
Collection
<
String
>
unUsedUrls
)
{
super
();
this
.
usedUrls
=
usedUrls
;
this
.
unUsedUrls
=
unUsedUrls
;
}
public
Collection
<
String
>
getUsedUrls
()
{
return
usedUrls
;
}
public
void
setUsedUrls
(
Collection
<
String
>
usedUrls
)
{
this
.
usedUrls
=
usedUrls
;
}
public
Collection
<
String
>
getUnUsedUrls
()
{
return
unUsedUrls
;
}
public
void
setUnUsedUrls
(
Collection
<
String
>
unUsedUrls
)
{
this
.
unUsedUrls
=
unUsedUrls
;
}
}
public
static
class
ClassLoaderStat
{
private
int
loadedCount
;
private
int
numberOfInstance
;
void
addLoadedCount
(
int
count
)
{
this
.
loadedCount
+=
count
;
}
void
addNumberOfInstance
(
int
count
)
{
this
.
numberOfInstance
+=
count
;
}
public
int
getLoadedCount
()
{
return
loadedCount
;
}
public
int
getNumberOfInstance
()
{
return
numberOfInstance
;
}
}
private
static
class
ValueComparator
implements
Comparator
<
String
>
{
private
Map
<
String
,
ClassLoaderStat
>
unsortedStats
;
ValueComparator
(
Map
<
String
,
ClassLoaderStat
>
stats
)
{
this
.
unsortedStats
=
stats
;
}
@Override
public
int
compare
(
String
o1
,
String
o2
)
{
if
(
null
==
unsortedStats
)
{
return
-
1
;
}
if
(!
unsortedStats
.
containsKey
(
o1
))
{
return
1
;
}
if
(!
unsortedStats
.
containsKey
(
o2
))
{
return
-
1
;
}
return
unsortedStats
.
get
(
o2
).
getLoadedCount
()
-
unsortedStats
.
get
(
o1
).
getLoadedCount
();
}
}
private
static
class
ClassLoaderInterruptHandler
implements
Handler
<
Void
>
{
private
ClassLoaderCommand
command
;
public
ClassLoaderInterruptHandler
(
ClassLoaderCommand
command
)
{
this
.
command
=
command
;
}
@Override
public
void
handle
(
Void
event
)
{
command
.
isInterrupted
=
true
;
}
}
}
core/src/main/java/com/taobao/arthas/core/command/klass100/DumpClassCommand.java
0 → 100644
View file @
7c094a26
package
com.taobao.arthas.core.command.klass100
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.model.ClassVO
;
import
com.taobao.arthas.core.command.model.ClassLoaderVO
;
import
com.taobao.arthas.core.command.model.DumpClassModel
;
import
com.taobao.arthas.core.command.model.DumpClassVO
;
import
com.taobao.arthas.core.command.model.MessageModel
;
import
com.taobao.arthas.core.command.model.RowAffectModel
;
import
com.taobao.arthas.core.shell.cli.Completion
;
import
com.taobao.arthas.core.shell.cli.CompletionUtils
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.shell.command.ExitStatus
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.arthas.core.util.ClassLoaderUtils
;
import
com.taobao.arthas.core.util.CommandUtils
;
import
com.taobao.arthas.core.util.InstrumentationUtils
;
import
com.taobao.arthas.core.util.SearchUtils
;
import
com.taobao.arthas.core.util.affect.RowAffect
;
import
com.taobao.middleware.cli.annotations.Argument
;
import
com.taobao.middleware.cli.annotations.DefaultValue
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Option
;
import
com.taobao.middleware.cli.annotations.Summary
;
import
java.io.File
;
import
java.lang.instrument.Instrumentation
;
import
java.lang.instrument.UnmodifiableClassException
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Collection
;
/**
* Dump class byte array
*/
@Name
(
"dump"
)
@Summary
(
"Dump class byte array from JVM"
)
@Description
(
Constants
.
EXAMPLE
+
" dump java.lang.String\n"
+
" dump -d /tmp/output java.lang.String\n"
+
" dump org/apache/commons/lang/StringUtils\n"
+
" dump *StringUtils\n"
+
" dump -E org\\\\.apache\\\\.commons\\\\.lang\\\\.StringUtils\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"dump"
)
public
class
DumpClassCommand
extends
AnnotatedCommand
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
DumpClassCommand
.
class
);
private
String
classPattern
;
private
String
code
=
null
;
private
String
classLoaderClass
;
private
boolean
isRegEx
=
false
;
private
String
directory
;
private
int
limit
;
@Argument
(
index
=
0
,
argName
=
"class-pattern"
)
@Description
(
"Class name pattern, use either '.' or '/' as separator"
)
public
void
setClassPattern
(
String
classPattern
)
{
this
.
classPattern
=
classPattern
;
}
@Option
(
shortName
=
"c"
,
longName
=
"code"
)
@Description
(
"The hash code of the special class's classLoader"
)
public
void
setCode
(
String
code
)
{
this
.
code
=
code
;
}
@Option
(
longName
=
"classLoaderClass"
)
@Description
(
"The class name of the special class's classLoader."
)
public
void
setClassLoaderClass
(
String
classLoaderClass
)
{
this
.
classLoaderClass
=
classLoaderClass
;
}
@Option
(
shortName
=
"E"
,
longName
=
"regex"
,
flag
=
true
)
@Description
(
"Enable regular expression to match (wildcard matching by default)"
)
public
void
setRegEx
(
boolean
regEx
)
{
isRegEx
=
regEx
;
}
@Option
(
shortName
=
"d"
,
longName
=
"directory"
)
@Description
(
"Sets the destination directory for class files"
)
public
void
setDirectory
(
String
directory
)
{
this
.
directory
=
directory
;
}
@Option
(
shortName
=
"l"
,
longName
=
"limit"
)
@Description
(
"The limit of dump classes size, default value is 50"
)
@DefaultValue
(
"50"
)
public
void
setLimit
(
int
limit
)
{
this
.
limit
=
limit
;
}
@Override
public
void
process
(
CommandProcess
process
)
{
RowAffect
effect
=
new
RowAffect
();
try
{
if
(
directory
!=
null
)
{
File
dir
=
new
File
(
directory
);
if
(
dir
.
isFile
())
{
process
.
end
(-
1
,
directory
+
" :is not a directory, please check it"
);
return
;
}
}
ExitStatus
status
=
null
;
Instrumentation
inst
=
process
.
session
().
getInstrumentation
();
if
(
code
==
null
&&
classLoaderClass
!=
null
)
{
List
<
ClassLoader
>
matchedClassLoaders
=
ClassLoaderUtils
.
getClassLoaderByClassName
(
inst
,
classLoaderClass
);
if
(
matchedClassLoaders
.
size
()
==
1
)
{
code
=
Integer
.
toHexString
(
matchedClassLoaders
.
get
(
0
).
hashCode
());
}
else
if
(
matchedClassLoaders
.
size
()
>
1
)
{
Collection
<
ClassLoaderVO
>
classLoaderVOList
=
ClassUtils
.
createClassLoaderVOList
(
matchedClassLoaders
);
DumpClassModel
dumpClassModel
=
new
DumpClassModel
()
.
setClassLoaderClass
(
classLoaderClass
)
.
setMatchedClassLoaders
(
classLoaderVOList
);
process
.
appendResult
(
dumpClassModel
);
process
.
end
(-
1
,
"Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'"
);
return
;
}
else
{
process
.
end
(-
1
,
"Can not find classloader by class name: "
+
classLoaderClass
+
"."
);
return
;
}
}
Set
<
Class
<?>>
matchedClasses
=
SearchUtils
.
searchClass
(
inst
,
classPattern
,
isRegEx
,
code
);
if
(
matchedClasses
==
null
||
matchedClasses
.
isEmpty
())
{
status
=
processNoMatch
(
process
);
}
else
if
(
matchedClasses
.
size
()
>
limit
)
{
status
=
processMatches
(
process
,
matchedClasses
);
}
else
{
status
=
processMatch
(
process
,
effect
,
inst
,
matchedClasses
);
}
process
.
appendResult
(
new
RowAffectModel
(
effect
));
CommandUtils
.
end
(
process
,
status
);
}
catch
(
Throwable
e
){
logger
.
error
(
"processing error"
,
e
);
process
.
end
(-
1
,
"processing error"
);
}
}
@Override
public
void
complete
(
Completion
completion
)
{
if
(!
CompletionUtils
.
completeClassName
(
completion
))
{
super
.
complete
(
completion
);
}
}
private
ExitStatus
processMatch
(
CommandProcess
process
,
RowAffect
effect
,
Instrumentation
inst
,
Set
<
Class
<?>>
matchedClasses
)
{
try
{
Map
<
Class
<?>,
File
>
classFiles
=
dump
(
inst
,
matchedClasses
);
List
<
DumpClassVO
>
dumpedClasses
=
new
ArrayList
<
DumpClassVO
>(
classFiles
.
size
());
for
(
Map
.
Entry
<
Class
<?>,
File
>
entry
:
classFiles
.
entrySet
())
{
Class
<?>
clazz
=
entry
.
getKey
();
File
file
=
entry
.
getValue
();
DumpClassVO
dumpClassVO
=
new
DumpClassVO
();
dumpClassVO
.
setLocation
(
file
.
getCanonicalPath
());
ClassUtils
.
fillSimpleClassVO
(
clazz
,
dumpClassVO
);
dumpedClasses
.
add
(
dumpClassVO
);
}
process
.
appendResult
(
new
DumpClassModel
().
setDumpedClasses
(
dumpedClasses
));
effect
.
rCnt
(
classFiles
.
keySet
().
size
());
return
ExitStatus
.
success
();
}
catch
(
Throwable
t
)
{
logger
.
error
(
"dump: fail to dump classes: "
+
matchedClasses
,
t
);
return
ExitStatus
.
failure
(-
1
,
"dump: fail to dump classes: "
+
matchedClasses
);
}
}
private
ExitStatus
processMatches
(
CommandProcess
process
,
Set
<
Class
<?>>
matchedClasses
)
{
String
msg
=
String
.
format
(
"Found more than %d class for: %s, Please Try to specify the classloader with the -c option, or try to use --limit option."
,
limit
,
classPattern
);
process
.
appendResult
(
new
MessageModel
(
msg
));
List
<
ClassVO
>
classVOs
=
ClassUtils
.
createClassVOList
(
matchedClasses
);
process
.
appendResult
(
new
DumpClassModel
().
setMatchedClasses
(
classVOs
));
return
ExitStatus
.
failure
(-
1
,
msg
);
}
private
ExitStatus
processNoMatch
(
CommandProcess
process
)
{
return
ExitStatus
.
failure
(-
1
,
"No class found for: "
+
classPattern
);
}
private
Map
<
Class
<?>,
File
>
dump
(
Instrumentation
inst
,
Set
<
Class
<?>>
classes
)
throws
UnmodifiableClassException
{
ClassDumpTransformer
transformer
=
null
;
if
(
directory
!=
null
)
{
transformer
=
new
ClassDumpTransformer
(
classes
,
new
File
(
directory
));
}
else
{
transformer
=
new
ClassDumpTransformer
(
classes
);
}
InstrumentationUtils
.
retransformClasses
(
inst
,
transformer
,
classes
);
return
transformer
.
getDumpResult
();
}
}
Prev
1
…
5
6
7
8
9
10
11
12
13
…
19
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment