WildFlyïŒä»¥åã®JBoss Application ServerïŒã¯ã2008幎2æã«JBossã«ãã£ãŠäœæããããªãŒãã³ãœãŒã¹ã®JavaEEã¢ããªã±ãŒã·ã§ã³ãµãŒããŒã§ãã WildFlyãããžã§ã¯ãã®äž»ãªç®æšã¯ããšã³ã¿ãŒãã©ã€ãºJavaã¢ããªã±ãŒã·ã§ã³ã§éåžžå¿ èŠãšãããäžé£ã®ããŒã«ãæäŸããããšã§ãããŸãããµãŒããŒã¯ãšã³ã¿ãŒãã©ã€ãºã¢ããªã±ãŒã·ã§ã³ã®éçºã«äœ¿çšãããããããšã©ãŒã®æ°ãšã³ãŒãå ã®æœåšçãªè匱æ§ãæå°éã«æããããšãç¹ã«éèŠã§ããçŸåšãWildFlyã¯å€§äŒæ¥ã®Red Hatã«ãã£ãŠéçºãããŠããããããžã§ã¯ãã³ãŒãã®å質ã¯ããªãé«ãã¬ãã«ã§ç¶æãããŠããŸãããã¢ãã©ã€ã¶ãŒã¯ãããžã§ã¯ãå ã®å€ãã®ãšã©ãŒãæ€åºããããšãã§ããŸããã
ç§ã®ååã¯ããããªãŒã§ããæè¿ãJavaããã°ã©ããŒãšããŠPVS-StudioããŒã ã«åå ããŸããããåç¥ã®ããã«ãã³ãŒãã¢ãã©ã€ã¶ãŒã«æ £ããã«ã¯ãå®éã«è©ŠããŠã¿ãã®ãäžçªã§ããããã§ãé¢çœããããžã§ã¯ããéžã³ããã§ãã¯ããŠããã®çµæã«åºã¥ããŠèšäºãæžãããšã«ããŸãããããã¯ããªããä»èªãã§ãããã®ã§ãã:)
ãããžã§ã¯ãåæ
åæã«ã¯ãGitHubã§å ¬éãããŠããWildFlyãããžã§ã¯ãã®ãœãŒã¹ã³ãŒãã䜿çšããŸãããClocã¯ã空çœãšã³ã¡ã³ããé€ããŠããããžã§ã¯ãã§60äžè¡ã®Javaã³ãŒããã«ãŠã³ãããŸãããã³ãŒãå ã®ãšã©ãŒã®æ€çŽ¢ã¯ãPVS-Studioã«ãã£ãŠå®è¡ãããŸãããPVS-Studioã¯ãCãC ++ãCïŒãããã³Javaã§èšè¿°ãããããã°ã©ã ã®ãœãŒã¹ã³ãŒãã®ãã°ãšæœåšçãªè匱æ§ãèŠã€ããããã®ããŒã«ã§ããIntelliJIDEAããŒãžã§ã³7.09ã®ã¢ãã©ã€ã¶ãŒãã©ã°ã€ã³ã䜿çšãããŸããã
ãããžã§ã¯ãããã§ãã¯ããçµæã491åã®ã¢ãã©ã€ã¶ãŒããªã¬ãŒã®ã¿ãåä¿¡ãããŸãããããã¯ãWildFlyã³ãŒãã®å質ãè¯å¥œã§ããããšã瀺ããŠããŸãããããã®ãã¡ã113ãé«ã§ã146ãäžã§ããåæã«ãããžãã£ãã®ãŸãšããªéšåã¯èšºæã«åœãŠã¯ãŸããŸãã
- V6002ãswitchã¹ããŒãã¡ã³ãã¯ãåæã®ãã¹ãŠã®å€ãç¶²çŸ ããŠããããã§ã¯ãããŸããã
- V6008ãæœåšçãªnulléåç §ã
- V6021ãå€ã¯ãxãå€æ°ã«å²ãåœãŠãããŸããã䜿çšãããŸããã
ãããã®èšºæãå®éã«ãšã©ãŒã§ãããã©ãããç解ããã®ã¯é£ããããããã®èšäºã§ã¯ãããã®èšºæã®ããªã¬ãŒã«ã€ããŠã¯èæ ®ããŠããŸããããã®ãããªèŠåã¯ãã³ãŒãã®äœæè ãæãããç解ããŠããŸãã
次ã«ãç§ãæãèå³æ·±ããšæã£ã10åã®ã¢ãã©ã€ã¶ãŒããªã¬ãŒãèŠãŠãããŸããå°ãã-ãªã10ïŒæ°ãããã®ããã§ãããšããçç±ã ãã§ã:)
ã§ã¯ãè¡ããŸãããã
èŠåN1ã¯åœ¹ã«ç«ããªãæ¡ä»¶æã§ã
V6004ãthenãã¹ããŒãã¡ã³ãã¯ãelseãã¹ããŒãã¡ã³ããšåçã§ããWeldPortableExtensionProcessor.javaïŒ61ïŒãWeldPortableExtensionProcessor.javaïŒ65ïŒã
@Override
public void deploy(DeploymentPhaseContext
phaseContext) throws DeploymentUnitProcessingException {
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
// for war modules we require a beans.xml to load portable extensions
if (PrivateSubDeploymentMarker.isPrivate(deploymentUnit)) {
if (!WeldDeploymentMarker.isPartOfWeldDeployment(deploymentUnit)) {
return;
}
} else {
// if any deployments have a beans.xml we need
// to load portable extensions
// even if this one does not.
if (!WeldDeploymentMarker.isPartOfWeldDeployment(deploymentUnit)) {
return;
}
}
}
å ã®ã³ãŒãã®å Žåãšãã以å€ã®æããããåããããã³æ¡ä»¶æŒç®åã¯ãçŸåšã®åœ¢ã§æå³ããããŸãããéçºè ããã®æ¹æ³ããã®ããã«æžããçç±ãèããã®ã¯é£ããã§ããã»ãšãã©ã®å Žåããšã©ãŒã¯ã³ããŒïŒããŒã¹ããŸãã¯ãªãã¡ã¯ã¿ãªã³ã°ã®çµæãšããŠçºçããŸããã
N2èŠå-éè€ããæ¡ä»¶
V6007åŒ 'poolStatsSize> 0'ã¯åžžã«çã§ããPooledConnectionFactoryStatisticsService.javaïŒ85ïŒ
@Override
public void start(StartContext context) throws StartException {
....
if (poolStatsSize > 0) {
if (registration != null) {
if (poolStatsSize > 0) {
....
}
}
}
}
ãã®å Žåãæ¡ä»¶ã®éè€ããããŸãããããã¯ããã°ã©ã ã®çµæã«ã¯åœ±é¿ããŸããããã³ãŒãã®èªã¿ããããæªåãããŸãããã ãã2çªç®ã®ãã§ãã¯ã«ä»ã®ãã匷åãªæ¡ä»¶ãå«ãŸããŠããå¯èœæ§ããããŸãã
WildFlyã§ããªã¬ãŒããããã®èšºæã®ä»ã®äŸïŒ
- V6007åŒ 'referralMode == null'ã¯åžžã«falseã§ããDirContext.javaïŒ93ïŒ
- V6007åŒ 'mBeanServer == null'ã¯åžžã«trueã§ããWildFlyServerPlatform.javaïŒ82ïŒ
- V6007åŒ 'resultïŒ= Null'ã¯åžžã«çã§ããNewã¯null以å€ã®åç §ãè¿ããŸããJarCheck.javaïŒ84ïŒ
- V6007åŒ 'çµæ'ã¯åžžã«çã§ããMultipleAdminObject2Impl.javaïŒ147ïŒ
èŠåN3-ãã«åç §ã«ããåç §
V6008ãtcãã®ãã«éåç §ãExternalPooledConnectionFactoryService.javaïŒ382ïŒ
private void createService(ServiceTarget serviceTarget,
ServiceContainer container) throws Exception {
....
for (TransportConfiguration tc : connectors) {
if (tc == null) {
throw MessagingLogger.ROOT_LOGGER.connectorNotDefined(tc.getName());
}
}
....
}
圌ãã¯æããã«ãããå°ç¡ãã«ããŸããããŸããåç §ãnullã§ããããšã確èªããŠããããã®éåžžã«nullã®åç §ã«å¯ŸããŠgetNameã¡ãœãããåŒã³åºããŸããããã«ãããconnectorNotDefinedïŒ....ïŒããäºæãããäŸå€ã§ã¯ãªããNullPointerExceptionãçºçããŸãã
èŠåN4-éåžžã«å¥åŠãªã³ãŒã
V6019å°éäžèœãªã³ãŒããæ€åºãããŸããããšã©ãŒãååšããå¯èœæ§ããããŸããEJB3Subsystem12Parser.javaïŒ79ïŒ
V6037ã«ãŒãå ã®ç¡æ¡ä»¶ã®ãã¹ããŒããEJB3Subsystem12Parser.javaïŒ81ïŒ
protected void readAttributes(final XMLExtendedStreamReader reader)
throws XMLStreamException {
for (int i = 0; i < reader.getAttributeCount(); i++) {
ParseUtils.requireNoNamespaceAttribute(reader, i);
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
V6019ãšV6037ã® 2ã€ã®èšºæãåæã«åå¿ããéåžžã«å¥åŠãªèšèšãããã§ã¯ãã«ãŒãã®1åã®å埩ã®ã¿ãå®è¡ããããã®åŸãç¡æ¡ä»¶ã®throwã«ãã£ãŠçµäºããŸãããã®ããããªãŒããŒã«å°ãªããšã1ã€ã®å±æ§ãå«ãŸããŠããå ŽåãreadAttributesã¡ãœããã¯äŸå€ãã¹ããŒããŸãããã®ã«ãŒãã¯ãåçã®æ¡ä»¶ã«çœ®ãæããããšãã§ããŸãã
if(reader.getAttributeCount() > 0) {
throw ParseUtils.unexpectedAttribute(reader, 0);
}
ãã ããããå°ãæ·±ãæãäžããŠãrequireNoNamespaceAttributeïŒ....ïŒã¡ãœããã確èªããããšãã§ããŸãã
public static void requireNoNamespaceAttribute
(XMLExtendedStreamReader reader, int index)
throws XMLStreamException {
if (!isNoNamespaceAttribute(reader, index)) {
throw unexpectedAttribute(reader, index);
}
}
ãã®ã¡ãœããã¯å éšçã«åãäŸå€ãã¹ããŒããããšãããããŸããã»ãšãã©ã®å ŽåãreadAttributesã¡ãœããã¯ãæå®ãããå±æ§ãã©ã®åååã«ãå±ããŠããªãããšãããã³å±æ§ãæ¬ èœããŠããªãããšã確èªããå¿ èŠããããŸãããã®ãããªæ§é ã¯ãã³ãŒãã®ãªãã¡ã¯ã¿ãªã³ã°ãšrequireNoNamespaceAttributeã¡ãœãããžã®äŸå€ã®ã¹ããŒã®çµæãšããŠçãããšèšãããã§ããã³ãããå±¥æŽãèŠãã ãã§ããã®ã³ãŒãããã¹ãŠåæã«è¿œå ãããããšãããããŸãã
èŠåN5-ã³ã³ã¹ãã©ã¯ã¿ãŒã«ãã©ã¡ãŒã¿ãŒãæž¡ã
V6022ãã©ã¡ãŒã¿ãŒ 'mechanismName'ã¯ã³ã³ã¹ãã©ã¯ã¿ãŒæ¬äœå ã§ã¯äœ¿çšãããŸãããDigestAuthenticationMechanism.javaïŒ144ïŒ
public DigestAuthenticationMechanism(final String realmName,
final String domain,
final String mechanismName,
final IdentityManager identityManager,
boolean validateUri) {
this(Collections.singletonList(DigestAlgorithm.MD5),
Collections.singletonList(DigestQop.AUTH),
realmName, domain, new SimpleNonceManager(),
DEFAULT_NAME, identityManager, validateUri);
}
éåžžãæªäœ¿çšã®å€æ°ãšé¢æ°ãã©ã¡ãŒã¿ãŒã¯éèŠãªãã®ã§ã¯ãããŸãããéåžžããããã¯ãªãã¡ã¯ã¿ãªã³ã°åŸããå°æ¥æ°ããæ©èœãå®è£ ããããã«è¿œå ãããåŸãæ®ããŸãããããããã®æäœã¯ç§ã«ã¯ããªãçãããããã§ããã
public DigestAuthenticationMechanism
(final List<DigestAlgorithm> supportedAlgorithms,
final List<DigestQop> supportedQops,
final String realmName,
final String domain,
final NonceManager nonceManager,
final String mechanismName,
final IdentityManager identityManager,
boolean validateUri) {....}
ã¯ã©ã¹ã®2çªç®ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãèŠããšãmechanizmNameæååã6çªç®ã®ãã©ã¡ãŒã¿ãŒãšããŠæ³å®ãããŠããããšãããããŸããæåã®ã³ã³ã¹ãã©ã¯ã¿ãŒã¯ã3çªç®ã®ãã©ã¡ãŒã¿ãŒãšåãååã®æååãåãåãã2çªç®ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºããŸãããã ãããã®æååã¯äœ¿çšãããã代ããã«å®æ°ã2çªç®ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããŸãããããããããã§ã®ã³ãŒãã®äœæè ã¯ãDEFAULT_NAMEå®æ°ã®ä»£ããã«mechanismNameãã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããšãèšç»ããŠããŸããã
èŠåN6-è¡ãéè€ããŠããŸã
V6033åãããŒãæã€ã¢ã€ãã 'org.apache.activemq.artemis.core.remoting.impl.nettyã
TransportConstants.NIO_REMOTING_THREADS_PROPNAME 'ã¯ãã§ã«è¿œå ãããŠããŸããLegacyConnectionFactoryService.javaïŒ145ïŒãLegacyConnectionFactoryService.javaïŒ139ïŒ
private static final Map<String, String>
PARAM_KEY_MAPPING = new HashMap<>();
....
static {
PARAM_KEY_MAPPING.put(
org.apache.activemq.artemis.core.remoting.impl.netty
.TransportConstants.NIO_REMOTING_THREADS_PROPNAME,
TransportConstants.NIO_REMOTING_THREADS_PROPNAME);
....
PARAM_KEY_MAPPING.put(
org.apache.activemq.artemis.core.remoting.impl.netty
.TransportConstants.NIO_REMOTING_THREADS_PROPNAME,
TransportConstants.NIO_REMOTING_THREADS_PROPNAME);
....
}
ã¢ãã©ã€ã¶ãŒã¯ãåãããŒãæã€2ã€ã®å€ãèŸæžã«è¿œå ãããããšãå ±åããŸãããã®å Žåãè¿œå ãããããŒãšå€ã®äžèŽã¯å®å šã«è€è£œãããŸããèšé²ãããå€ã¯TransportConstantsã¯ã©ã¹ã®å®æ°ã§ãããäœæè ã誀ã£ãŠã³ãŒããè€è£œããããã³ããŒè²Œãä»ãäžã«å€ãå€æŽããã®ãå¿ãããšãã2ã€ã®ãªãã·ã§ã³ã®ããããããããŸãããã£ãšèª¿ã¹ããšãããäžè¶³ããŠããããŒãšå€ãèŠã€ãããªãã£ãã®ã§ãæåã®ã·ããªãªã®å¯èœæ§ãé«ããšæããŸãã
èŠåN7-å€æ°ã倱ãããŸãã
V6046ãã©ãŒããããæ£ãããããŸãããç°ãªãæ°ã®ãã©ãŒãããã¢ã€ãã ãäºæ³ãããŸããæ¬ èœããŠããåŒæ°ïŒ2ãTxTestUtil.javaïŒ80ïŒ
public static void addSynchronization(TransactionManager tm,
TransactionCheckerSingletonRemote checker) {
try {
addSynchronization(tm.getTransaction(), checker);
} catch (SystemException se) {
throw new RuntimeException(String
.format("Can't obtain transaction for transaction manager '%s' "
+ "to enlist add test synchronization '%s'"), se);
}
}
å€æ°ã倱ãããŸãïŒå¿ èŠã§ãïŒããã©ãŒããããããæååã«ã¯ä»ã®2è¡ãä»£å ¥ãããã¯ãã§ããããã³ãŒãã®äœæè ã¯æããã«ããããè¿œå ããã®ãå¿ããŠããŸãããé©åãªåŒæ°ãªãã§æååããã©ãŒããããããšãéçºè ãæå³ããRuntimeExceptionã®ä»£ããã«IllegalFormatExceptionãã¹ããŒãããŸããååãšããŠãIllegalFormatExceptionã¯RuntimeExceptionãç¶æ¿ããŸãããäŸå€ã«æž¡ãããã¡ãã»ãŒãžã¯åºåã§å€±ããããããã°æã«æ£ç¢ºã«äœãæªãã£ãã®ããç解ããã®ãããå°é£ã«ãªããŸãã
èŠåN8-æååãšãªããžã§ã¯ãã®æ¯èŒ
V6058'equals 'é¢æ°ã¯ãäºææ§ã®ãªãã¿ã€ãã®ãªããžã§ã¯ãïŒStringãModelNodeïŒãæ¯èŒããŸããJaxrsIntegrationProcessor.javaïŒ563ïŒ
// Send value to RESTEasy only if it's not null, empty string, or the
// default value.
private boolean isTransmittable(AttributeDefinition attribute,
ModelNode modelNode) {
if (modelNode == null || ModelType
.UNDEFINED.equals(modelNode.getType())) {
return false;
}
String value = modelNode.asString();
if ("".equals(value.trim())) {
return false;
}
return !value.equals(attribute.getDefaultValue()); // <=
}
ãã®å Žåãæååã¯ãªããžã§ã¯ããšæ¯èŒããããã®ãããªæ¯èŒã¯åžžã«falseã§ããã€ãŸããattribute.getDefaultValueïŒïŒã«çããmodelNodeå€ãã¡ãœããã«æž¡ãããå Žåãã¡ãœããã®åäœã¯æ£ãããªãããšãå€æããã³ã¡ã³ãã«ãããããããå€ã¯éä¿¡ã«å¯ŸããŠæå¹ã§ãããšèªèãããŸãã ã»ãšãã©ã®å Žåã圌ãã¯ãattribute.getDefaultValueïŒïŒãæååãšããŠè¡šãããã«asStringïŒïŒã¡ãœãããåŒã³åºãã®ãå¿ããŠããŸãããä¿®æ£ãããããŒãžã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
return !value.equals(attribute.getDefaultValue().asString());
WildFlyã«ã¯ãV6058蚺æã®ãã1ã€ã®åæ§ã®ããªã¬ãŒããããŸãã
- V6058'equals 'é¢æ°ã¯ãäºææ§ã®ãªãã¿ã€ãã®ãªããžã§ã¯ãïŒStringãObjectTypeAttributeDefinitionïŒãæ¯èŒããŸããDataSourceDefinition.javaïŒ141ïŒ
èŠåN9-ã¬ã€ããã§ãã¯
V6060'dataSourceController 'åç §ã¯ãnullã«å¯ŸããŠæ€èšŒãããåã«äœ¿çšãããŸãããAbstractDataSourceAdd.javaïŒ399ïŒãAbstractDataSourceAdd.javaïŒ297ïŒ
static void secondRuntimeStep(OperationContext context, ModelNode operation,
ManagementResourceRegistration datasourceRegistration,
ModelNode model, boolean isXa) throws OperationFailedException {
final ServiceController<?> dataSourceController =
registry.getService(dataSourceServiceName);
....
dataSourceController.getService()
....
if (dataSourceController != null) {....}
....
}
ã¢ãã©ã€ã¶ãŒã¯ããªããžã§ã¯ããnullã§ãããã©ããããã§ãã¯ããããã£ãšåã«ã³ãŒãã§äœ¿çšãããŠããããããã®éã®è·é¢ã102è¡ãã®ã³ãŒãã§ããããšãæ€åºããŸãããããã¯ãã³ãŒããæåã§åæãããšãã«æ°ä»ãã®ãéåžžã«å°é£ã§ãã
èŠåN10-ããã¯ã®å確èª
V6082å®å šã§ãªãããã«ãã§ãã¯ããã¯ã以åã«å²ãåœãŠããããªããžã§ã¯ãã¯ãå¥ã®ãªããžã§ã¯ãã«çœ®ãæããããšãã§ããŸãã JspApplicationContextWrapper.javaïŒ74ïŒãJspApplicationContextWrapper.javaïŒ72ïŒ
private volatile ExpressionFactory factory;
....
@Override
public ExpressionFactory getExpressionFactory() {
if (factory == null) {
synchronized (this) {
if (factory == null) {
factory = delegate.getExpressionFactory();
for (ExpressionFactoryWrapper wrapper : wrapperList) {
factory = wrapper.wrap(factory, servletContext);
}
}
}
}
return factory;
}
ããã¯ãããã«ãã§ãã¯ããã¯ããã¿ãŒã³ã䜿çšããã¡ãœãããäžå®å šã«åæåãããå€æ°ãè¿ãå ŽåããããŸãã
ã¹ã¬ããAã¯ãå€ãåæåãããŠããªãããšã«æ°ä»ãããããããã¯ãååŸããŠå€ã®åæåãéå§ããŸãããã®å Žåãã¹ã¬ããã¯ããªããžã§ã¯ããæåŸãŸã§åæåãããåã§ãã£ãŠãããªããžã§ã¯ãããã£ãŒã«ãã«æžã蟌ãããšãã§ããŸããã¹ã¬ããBã¯ããªããžã§ã¯ããäœæãããããšãæ€åºããŠè¿ããŸãããã¹ã¬ããAã«ã¯ããã¡ã¯ããªã§ãã¹ãŠã®äœæ¥ãè¡ãæéããŸã ãããŸããã
ãã®çµæãèšç»ããããã¹ãŠã®ã¢ã¯ã·ã§ã³ãå®è¡ãããŠããªããªããžã§ã¯ããã¡ãœããããè¿ãããå ŽåããããŸãã
çµè«
ãããžã§ã¯ãã¯å€§äŒæ¥ã®RedHatã«ãã£ãŠéçºãããŠããããããžã§ã¯ãã®ã³ãŒãã®å質ã¯é«ã¬ãã«ã§ããã«ãããããããPVS-Studioã䜿çšããŠå®è¡ãããéçåæã«ããããµãŒããŒã®åäœã«äœããã®åœ±é¿ãäžããå¯èœæ§ã®ããç¹å®ã®æ°ã®ãšã©ãŒãæããã«ããããšãã§ããŸããããŸããWildFlyã¯ãšã³ã¿ãŒãã©ã€ãºã¢ããªã±ãŒã·ã§ã³ãäœæããããã«èšèšãããŠããããããããã®ééãã¯éåžžã«æ²ããçµæã«ã€ãªããå¯èœæ§ããããŸãã
PVS-StudioãããŠã³ããŒãããŠããããžã§ã¯ãã確èªããŠãã ããããããè¡ãã«ã¯ããã©ã€ã¢ã«ã©ã€ã»ã³ã¹ããªã¯ãšã¹ãããããç¡æã®ãŠãŒã¹ã±ãŒã¹ã®1ã€ã䜿çšã§ããŸãã
ãã®èšäºãè±èªã話ãèŽè¡ãšå ±æãããå Žåã¯ã翻蚳ãªã³ã¯DmitryScherbakovã䜿çšããŠãã ãããJavaEEã¢ããªã±ãŒã·ã§ã³ãµãŒããŒã§ããWildFlyããã§ãã¯ããŠããŸãã