diff --git a/Makefile.config b/Makefile.config
index 3613a3c7e88..51c57628714 100644
--- a/Makefile.config
+++ b/Makefile.config
@@ -96,11 +96,18 @@ GUAVA_JAR = $(DEPENDENCIES_DIR)/java/guava/guava-23.0.jar
 INFER_ANNOTATIONS_JAR = $(ANNOTATIONS_DIR)/annotations.jar
 JACKSON_JAR = $(DEPENDENCIES_DIR)/java/jackson/jackson-2.2.3.jar
 JSR_305_JAR = $(DEPENDENCIES_DIR)/java/jsr-305/jsr305.jar
+COMMONS_JAR = $(DEPENDENCIES_DIR)/java/commons/commons-lang-2.6.jar
+COMMONS3_JAR = $(DEPENDENCIES_DIR)/java/commons/commons-lang3-3.0.jar
+LOMBOK_JAR = $(DEPENDENCIES_DIR)/java/lombok/lombok-1.18.20.jar
+S3_JAR = $(DEPENDENCIES_DIR)/java/aws/s3-abi.jar
+KMS_JAR = $(DEPENDENCIES_DIR)/java/aws/kms-abi.jar
+DDB_JAR = $(DEPENDENCIES_DIR)/java/aws/ddb-abi.jar
 
 JAVA_MODELS_JAR = $(LIB_DIR)/java/models.jar
 
 JAVA_DEPS_NO_MODELS = \
   $(ANDROID_JAR) $(GUAVA_JAR) $(JACKSON_JAR) $(JSR_305_JAR) $(INFER_ANNOTATIONS_JAR) \
+  $(COMMONS_JAR) $(COMMONS3_JAR) $(LOMBOK_JAR) \
   $(INFER_BIN)
 
 JAVA_DEPS = $(JAVA_DEPS_NO_MODELS) $(JAVA_MODELS_JAR) $(MODELS_RESULTS_FILE)
diff --git a/dependencies/java/aws/ddb-abi.jar b/dependencies/java/aws/ddb-abi.jar
new file mode 100644
index 00000000000..4a1414da6d9
Binary files /dev/null and b/dependencies/java/aws/ddb-abi.jar differ
diff --git a/dependencies/java/aws/kms-abi.jar b/dependencies/java/aws/kms-abi.jar
new file mode 100644
index 00000000000..da1dde8318c
Binary files /dev/null and b/dependencies/java/aws/kms-abi.jar differ
diff --git a/dependencies/java/aws/s3-abi.jar b/dependencies/java/aws/s3-abi.jar
new file mode 100644
index 00000000000..f9e6e7d6c5b
Binary files /dev/null and b/dependencies/java/aws/s3-abi.jar differ
diff --git a/dependencies/java/commons/commons-lang-2.6.jar b/dependencies/java/commons/commons-lang-2.6.jar
new file mode 100644
index 00000000000..98467d3a653
Binary files /dev/null and b/dependencies/java/commons/commons-lang-2.6.jar differ
diff --git a/dependencies/java/commons/commons-lang3-3.0.jar b/dependencies/java/commons/commons-lang3-3.0.jar
new file mode 100644
index 00000000000..7f2cfe13f69
Binary files /dev/null and b/dependencies/java/commons/commons-lang3-3.0.jar differ
diff --git a/dependencies/java/lombok/lombok-1.18.20.jar b/dependencies/java/lombok/lombok-1.18.20.jar
new file mode 100644
index 00000000000..d3434f6944e
Binary files /dev/null and b/dependencies/java/lombok/lombok-1.18.20.jar differ
diff --git a/infer/models/Makefile b/infer/models/Makefile
index bd302b1e114..f9b2c86fc16 100644
--- a/infer/models/Makefile
+++ b/infer/models/Makefile
@@ -19,7 +19,7 @@ JAVA_MODELS_OUT = java/models
 MODELS_JAR = models.jar
 
 JAVA_SOURCES = $(shell find $(JAVA_BUILTINS_DIR) $(JAVA_MODELS_DIR) -name "*.java")
-JAVA_MODELS_CLASSPATH = $(ANDROID_JAR):$(GUAVA_JAR):$(JACKSON_JAR):$(JSR_305_JAR):$(INFER_ANNOTATIONS_JAR)
+JAVA_MODELS_CLASSPATH = $(ANDROID_JAR):$(GUAVA_JAR):$(JACKSON_JAR):$(JSR_305_JAR):$(INFER_ANNOTATIONS_JAR):$(COMMONS_JAR):$(COMMONS3_JAR):$(LOMBOK_JAR):$(S3_JAR):$(DDB_JAR):$(KMS_JAR)
 JAVAC_OPTIONS = -bootclasspath $(ANDROID_JAR) -d $(JAVA_MODELS_OUT) -classpath $(JAVA_MODELS_CLASSPATH) \
 	$(JAVA_SOURCES) -source 7 -target 7
 
diff --git a/infer/models/java/src/com/amazonaws/AmazonClientException.java b/infer/models/java/src/com/amazonaws/AmazonClientException.java
new file mode 100644
index 00000000000..b2c620e33a4
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/AmazonClientException.java
@@ -0,0 +1,5 @@
+package com.amazonaws;
+
+public class AmazonClientException {
+   public AmazonClientException () {}
+}
diff --git a/infer/models/java/src/com/amazonaws/metrics/RequestMetricCollector.java b/infer/models/java/src/com/amazonaws/metrics/RequestMetricCollector.java
new file mode 100644
index 00000000000..eba597ee251
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/metrics/RequestMetricCollector.java
@@ -0,0 +1,5 @@
+package com.amazonaws.metrics;
+
+public class RequestMetricCollector {
+   public RequestMetricCollector () {}
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/AbstractDynamoDBMapper.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/AbstractDynamoDBMapper.java
new file mode 100644
index 00000000000..918ed6962d2
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/AbstractDynamoDBMapper.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.datamodeling;
+import java.util.Map;
+public class AbstractDynamoDBMapper {
+   public AbstractDynamoDBMapper () {}
+   public <T> T load(T keyObject, DynamoDBMapperConfig config) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.java
new file mode 100644
index 00000000000..d221bf0da8f
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.java
@@ -0,0 +1,11 @@
+package com.amazonaws.services.dynamodbv2.datamodeling;
+import java.util.Map;
+public class DynamoDBMapper {
+   public DynamoDBMapper () {}
+   public <T> T load(Class<T> clazz, Object hashKey) {
+      return null;
+   }
+   public <T> T load(Class<T> clazz, Object hashKey, Object rangeKey, DynamoDBMapperConfig config) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.java
new file mode 100644
index 00000000000..919b3db4a65
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapperConfig.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.datamodeling;
+import com.amazonaws.metrics.RequestMetricCollector;
+public class DynamoDBMapperConfig {
+   public DynamoDBMapperConfig () {}
+   public RequestMetricCollector getRequestMetricCollector() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBScanExpression.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBScanExpression.java
new file mode 100644
index 00000000000..90c09bceaf4
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBScanExpression.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.datamodeling;
+
+public class DynamoDBScanExpression {
+   public DynamoDBScanExpression () {}
+   public String getIndexName() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/QueryResultPage.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/QueryResultPage.java
new file mode 100644
index 00000000000..915f2b8f17e
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/QueryResultPage.java
@@ -0,0 +1,9 @@
+package com.amazonaws.services.dynamodbv2.datamodeling;
+import java.util.Map;
+import com.amazonaws.services.dynamodbv2.model.AttributeValue;
+public class QueryResultPage<T> {
+   public QueryResultPage () {}
+   public Map<String,AttributeValue> getLastEvaluatedKey() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/ScanResultPage.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/ScanResultPage.java
new file mode 100644
index 00000000000..61a83fbae36
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/datamodeling/ScanResultPage.java
@@ -0,0 +1,9 @@
+package com.amazonaws.services.dynamodbv2.datamodeling;
+import java.util.Map;
+import com.amazonaws.services.dynamodbv2.model.AttributeValue;
+public class ScanResultPage<T> {
+   public ScanResultPage () {}
+   public Map<String,AttributeValue> getLastEvaluatedKey() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/DeleteItemOutcome.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/DeleteItemOutcome.java
new file mode 100644
index 00000000000..1eb33ea1f4e
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/DeleteItemOutcome.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.document;
+
+public class DeleteItemOutcome {
+   public DeleteItemOutcome () {}
+   public Item getItem() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/GetItemOutcome.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/GetItemOutcome.java
new file mode 100644
index 00000000000..f3decc3245a
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/GetItemOutcome.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.document;
+
+public class GetItemOutcome {
+   public GetItemOutcome () {}
+   public Item getItem() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/Item.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/Item.java
new file mode 100644
index 00000000000..42b56d2e29d
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/Item.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.document;
+
+public class Item {
+   public Item () {}
+   public Class<?> getTypeOf(String attrName) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/ItemUtils.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/ItemUtils.java
new file mode 100644
index 00000000000..c5814954960
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/ItemUtils.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.document;
+
+public class ItemUtils {
+   public ItemUtils () {}
+   public static Integer minimum(Integer one, Integer two) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/Table.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/Table.java
new file mode 100644
index 00000000000..ebeb24f89d9
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/Table.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.document;
+import com.amazonaws.services.dynamodbv2.model.TableDescription;
+public class Table {
+   public Table () {}
+   public TableDescription getDescription() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/internal/InternalUtils.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/internal/InternalUtils.java
new file mode 100644
index 00000000000..4bd89056774
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/document/internal/InternalUtils.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.document.internal;
+
+public class InternalUtils {
+   public InternalUtils () {}
+   public static Integer minimum(Integer one, Integer two) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/DeleteItemExpressionSpec.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/DeleteItemExpressionSpec.java
new file mode 100644
index 00000000000..a02ac510857
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/DeleteItemExpressionSpec.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.xspec;
+import java.util.Map;
+public class DeleteItemExpressionSpec {
+   public DeleteItemExpressionSpec () {}
+   public final Map<String,Object> getValueMap() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/GetItemExpressionSpec.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/GetItemExpressionSpec.java
new file mode 100644
index 00000000000..d5072c5e557
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/GetItemExpressionSpec.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.xspec;
+import java.util.Map;
+public class GetItemExpressionSpec {
+   public GetItemExpressionSpec () {}
+   public final Map<String,String> getNameMap() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/PutItemExpressionSpec.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/PutItemExpressionSpec.java
new file mode 100644
index 00000000000..9e874a20b50
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/PutItemExpressionSpec.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.xspec;
+import java.util.Map;
+public class PutItemExpressionSpec {
+   public PutItemExpressionSpec () {}
+   public Map<String,Object> getValueMap() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/QueryExpressionSpec.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/QueryExpressionSpec.java
new file mode 100644
index 00000000000..3783f9147b8
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/QueryExpressionSpec.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.xspec;
+import java.util.Map;
+public class QueryExpressionSpec {
+   public QueryExpressionSpec () {}
+   public Map<String,Object> getValueMap() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/ScanExpressionSpec.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/ScanExpressionSpec.java
new file mode 100644
index 00000000000..7341ee2d9cc
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/ScanExpressionSpec.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.xspec;
+import java.util.Map;
+public class ScanExpressionSpec {
+   public ScanExpressionSpec () {}
+   public Map<String,Object> getValueMap() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/UpdateItemExpressionSpec.java b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/UpdateItemExpressionSpec.java
new file mode 100644
index 00000000000..011a429ea00
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/dynamodbv2/xspec/UpdateItemExpressionSpec.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.dynamodbv2.xspec;
+import java.util.Map;
+public class UpdateItemExpressionSpec {
+   public UpdateItemExpressionSpec () {}
+   public Map<String,Object> getValueMap() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/elasticmapreduce/spi/security/EncryptionMaterials.java b/infer/models/java/src/com/amazonaws/services/elasticmapreduce/spi/security/EncryptionMaterials.java
new file mode 100644
index 00000000000..428a00c6757
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/elasticmapreduce/spi/security/EncryptionMaterials.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.elasticmapreduce.spi.security;
+import java.util.Map;
+public class EncryptionMaterials {
+   public EncryptionMaterials () {}
+   public Map<String,String> getMaterialsDescription() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/kinesisvideo/model/AckErrorCode/Values.java b/infer/models/java/src/com/amazonaws/services/kinesisvideo/model/AckErrorCode/Values.java
new file mode 100644
index 00000000000..9b0a5d188dd
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/kinesisvideo/model/AckErrorCode/Values.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.kinesisvideo.model.AckErrorCode;
+
+public class Values {
+   public Values () {}
+   public String toString() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/kinesisvideo/model/AckEventType/Values.java b/infer/models/java/src/com/amazonaws/services/kinesisvideo/model/AckEventType/Values.java
new file mode 100644
index 00000000000..4e74c610f65
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/kinesisvideo/model/AckEventType/Values.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.kinesisvideo.model.AckEventType;
+
+public class Values {
+   public Values () {}
+   public String toString() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/kms/AWSKMS.java b/infer/models/java/src/com/amazonaws/services/kms/AWSKMS.java
new file mode 100644
index 00000000000..b1f73bae769
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/kms/AWSKMS.java
@@ -0,0 +1,5 @@
+package com.amazonaws.services.kms;
+
+public class AWSKMS {
+   public AWSKMS () {}
+}
diff --git a/infer/models/java/src/com/amazonaws/services/mediaconvert/model/Job.java b/infer/models/java/src/com/amazonaws/services/mediaconvert/model/Job.java
new file mode 100644
index 00000000000..357494152b2
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/mediaconvert/model/Job.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.mediaconvert.model;
+
+public class Job {
+   public Job () {}
+   public Job withJobPercentComplete(Integer jobPercentComplete) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/AmazonS3Client.java b/infer/models/java/src/com/amazonaws/services/s3/AmazonS3Client.java
new file mode 100644
index 00000000000..27fb6c45bc9
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/AmazonS3Client.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3;
+
+public class AmazonS3Client {
+   public AmazonS3Client () {}
+   public String getResourceUrl(String bucketName, String key) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/AmazonS3EncryptionClientV2.java b/infer/models/java/src/com/amazonaws/services/s3/AmazonS3EncryptionClientV2.java
new file mode 100644
index 00000000000..cad4a80e418
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/AmazonS3EncryptionClientV2.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3;
+import com.amazonaws.services.kms.AWSKMS;
+public class AmazonS3EncryptionClientV2 {
+   public AmazonS3EncryptionClientV2 () {}
+   public AWSKMS getKmsClient() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/internal/PartCreationEvent.java b/infer/models/java/src/com/amazonaws/services/s3/internal/PartCreationEvent.java
new file mode 100644
index 00000000000..449124141e5
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/internal/PartCreationEvent.java
@@ -0,0 +1,9 @@
+package com.amazonaws.services.s3.internal;
+import java.io.File;
+import com.amazonaws.services.s3.OnFileDelete;
+public class PartCreationEvent {
+   public PartCreationEvent () {}
+   public OnFileDelete getFileDeleteObserver() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/internal/RepeatableFileInputStream.java b/infer/models/java/src/com/amazonaws/services/s3/internal/RepeatableFileInputStream.java
new file mode 100644
index 00000000000..b69f4b8d8b1
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/internal/RepeatableFileInputStream.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.internal;
+import java.io.InputStream;
+public class RepeatableFileInputStream {
+   public RepeatableFileInputStream () {}
+   public InputStream getWrappedInputStream() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/internal/RepeatableInputStream.java b/infer/models/java/src/com/amazonaws/services/s3/internal/RepeatableInputStream.java
new file mode 100644
index 00000000000..6ac71a9be25
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/internal/RepeatableInputStream.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.internal;
+import java.io.InputStream;
+public class RepeatableInputStream {
+   public RepeatableInputStream () {}
+   public InputStream getWrappedInputStream() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/internal/S3XmlResponseHandler.java b/infer/models/java/src/com/amazonaws/services/s3/internal/S3XmlResponseHandler.java
new file mode 100644
index 00000000000..f9c49ab02c7
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/internal/S3XmlResponseHandler.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.internal;
+import java.util.Map;
+public class S3XmlResponseHandler<T> {
+   public S3XmlResponseHandler () {}
+   public Map<String,String> getResponseHeaders() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/internal/SSEResultBase.java b/infer/models/java/src/com/amazonaws/services/s3/internal/SSEResultBase.java
new file mode 100644
index 00000000000..82e0a1543d6
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/internal/SSEResultBase.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.internal;
+
+public class SSEResultBase {
+   public SSEResultBase () {}
+   public final String getSSECustomerKeyMd5() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/internal/crypto/GCMCipherLite.java b/infer/models/java/src/com/amazonaws/services/s3/internal/crypto/GCMCipherLite.java
new file mode 100644
index 00000000000..08c1c13cea4
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/internal/crypto/GCMCipherLite.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.internal.crypto;
+
+public class GCMCipherLite {
+   public GCMCipherLite () {}
+   public byte[] getTag() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/AmazonS3Exception.java b/infer/models/java/src/com/amazonaws/services/s3/model/AmazonS3Exception.java
new file mode 100644
index 00000000000..bd185f179ca
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/AmazonS3Exception.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class AmazonS3Exception {
+   public AmazonS3Exception () {}
+   public String getErrorResponseXml() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/Bucket.java b/infer/models/java/src/com/amazonaws/services/s3/model/Bucket.java
new file mode 100644
index 00000000000..eef8db11a67
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/Bucket.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+import java.util.Date;
+public class Bucket {
+   public Bucket () {}
+   public Date getCreationDate() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/CompleteMultipartUploadResult.java b/infer/models/java/src/com/amazonaws/services/s3/model/CompleteMultipartUploadResult.java
new file mode 100644
index 00000000000..d5c92c7aa5c
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/CompleteMultipartUploadResult.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class CompleteMultipartUploadResult {
+   public CompleteMultipartUploadResult () {}
+   public String getExpirationTimeRuleId() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/CopyObjectResult.java b/infer/models/java/src/com/amazonaws/services/s3/model/CopyObjectResult.java
new file mode 100644
index 00000000000..f72e53a5dc0
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/CopyObjectResult.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class CopyObjectResult {
+   public CopyObjectResult () {}
+   public String getExpirationTimeRuleId() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/EncryptionMaterials.java b/infer/models/java/src/com/amazonaws/services/s3/model/EncryptionMaterials.java
new file mode 100644
index 00000000000..897c085b9d6
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/EncryptionMaterials.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+import com.amazonaws.services.s3.model.EncryptionMaterialsAccessor;
+public class EncryptionMaterials {
+   public EncryptionMaterials () {}
+   public EncryptionMaterialsAccessor getAccessor() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/GeneratePresignedUrlRequest.java b/infer/models/java/src/com/amazonaws/services/s3/model/GeneratePresignedUrlRequest.java
new file mode 100644
index 00000000000..721520697eb
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/GeneratePresignedUrlRequest.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class GeneratePresignedUrlRequest {
+   public GeneratePresignedUrlRequest () {}
+   public String getSSEAlgorithm() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/GroupGrantee.java b/infer/models/java/src/com/amazonaws/services/s3/model/GroupGrantee.java
new file mode 100644
index 00000000000..7dd2f5de4a0
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/GroupGrantee.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class GroupGrantee {
+   public GroupGrantee () {}
+   public static GroupGrantee parseGroupGrantee(String groupUri) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/KMSEncryptionMaterials.java b/infer/models/java/src/com/amazonaws/services/s3/model/KMSEncryptionMaterials.java
new file mode 100644
index 00000000000..fa15e35615d
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/KMSEncryptionMaterials.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class KMSEncryptionMaterials {
+   public KMSEncryptionMaterials () {}
+   public String getCustomerMasterKeyId() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/ListMultipartUploadsRequest.java b/infer/models/java/src/com/amazonaws/services/s3/model/ListMultipartUploadsRequest.java
new file mode 100644
index 00000000000..95431cf4b38
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/ListMultipartUploadsRequest.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class ListMultipartUploadsRequest {
+   public ListMultipartUploadsRequest () {}
+   public Integer getMaxUploads() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/MultiObjectDeleteException.java b/infer/models/java/src/com/amazonaws/services/s3/model/MultiObjectDeleteException.java
new file mode 100644
index 00000000000..e7d2c8531c5
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/MultiObjectDeleteException.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class MultiObjectDeleteException {
+   public MultiObjectDeleteException () {}
+   public String getErrorCode() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/MultipartUploadListing.java b/infer/models/java/src/com/amazonaws/services/s3/model/MultipartUploadListing.java
new file mode 100644
index 00000000000..d9c77ec394c
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/MultipartUploadListing.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class MultipartUploadListing {
+   public MultipartUploadListing () {}
+   public String getPrefix() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/ObjectListing.java b/infer/models/java/src/com/amazonaws/services/s3/model/ObjectListing.java
new file mode 100644
index 00000000000..b319b4f29e8
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/ObjectListing.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class ObjectListing {
+   public ObjectListing () {}
+   public String getNextMarker() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/ObjectMetadata.java b/infer/models/java/src/com/amazonaws/services/s3/model/ObjectMetadata.java
new file mode 100644
index 00000000000..331a62cce99
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/ObjectMetadata.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+import java.util.Date;
+public class ObjectMetadata {
+   public ObjectMetadata () {}
+   public Date getRestoreExpirationTime() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/Permission.java b/infer/models/java/src/com/amazonaws/services/s3/model/Permission.java
new file mode 100644
index 00000000000..93a23f32478
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/Permission.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class Permission {
+   public Permission () {}
+   public static Permission parsePermission(String str) {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/PresignedUrlUploadResult.java b/infer/models/java/src/com/amazonaws/services/s3/model/PresignedUrlUploadResult.java
new file mode 100644
index 00000000000..873019cb714
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/PresignedUrlUploadResult.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class PresignedUrlUploadResult {
+   public PresignedUrlUploadResult () {}
+   public String getContentMd5() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/PutInstructionFileRequest.java b/infer/models/java/src/com/amazonaws/services/s3/model/PutInstructionFileRequest.java
new file mode 100644
index 00000000000..33d55535179
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/PutInstructionFileRequest.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class PutInstructionFileRequest {
+   public PutInstructionFileRequest () {}
+   public EncryptionMaterials getEncryptionMaterials() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/PutObjectResult.java b/infer/models/java/src/com/amazonaws/services/s3/model/PutObjectResult.java
new file mode 100644
index 00000000000..e608ede98c7
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/PutObjectResult.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class PutObjectResult {
+   public PutObjectResult () {}
+   public String getContentMd5() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/Region.java b/infer/models/java/src/com/amazonaws/services/s3/model/Region.java
new file mode 100644
index 00000000000..a2bba01d789
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/Region.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class Region {
+   public Region () {}
+   public String getFirstRegionId() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/S3ObjectSummary.java b/infer/models/java/src/com/amazonaws/services/s3/model/S3ObjectSummary.java
new file mode 100644
index 00000000000..0e1bf973963
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/S3ObjectSummary.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+import com.amazonaws.services.s3.model.Owner;
+public class S3ObjectSummary {
+   public S3ObjectSummary () {}
+   public Owner getOwner() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/S3VersionSummary.java b/infer/models/java/src/com/amazonaws/services/s3/model/S3VersionSummary.java
new file mode 100644
index 00000000000..be065e2d5b3
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/S3VersionSummary.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+import com.amazonaws.services.s3.model.Owner;
+public class S3VersionSummary {
+   public S3VersionSummary () {}
+   public Owner getOwner() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/UploadObjectRequest.java b/infer/models/java/src/com/amazonaws/services/s3/model/UploadObjectRequest.java
new file mode 100644
index 00000000000..ecbda45ed06
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/UploadObjectRequest.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+import com.amazonaws.services.s3.UploadObjectObserver;
+public class UploadObjectRequest {
+   public UploadObjectRequest () {}
+   public UploadObjectObserver getUploadObjectObserver() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/model/VersionListing.java b/infer/models/java/src/com/amazonaws/services/s3/model/VersionListing.java
new file mode 100644
index 00000000000..e05092035f7
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/model/VersionListing.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.model;
+
+public class VersionListing {
+   public VersionListing () {}
+   public String getNextVersionIdMarker() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/transfer/internal/AbstractTransfer.java b/infer/models/java/src/com/amazonaws/services/s3/transfer/internal/AbstractTransfer.java
new file mode 100644
index 00000000000..bb66b22de21
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/transfer/internal/AbstractTransfer.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.transfer.internal;
+import com.amazonaws.AmazonClientException;
+public class AbstractTransfer {
+   public AbstractTransfer () {}
+   public AmazonClientException waitForException() throws InterruptedException {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/services/s3/transfer/internal/DownloadImpl.java b/infer/models/java/src/com/amazonaws/services/s3/transfer/internal/DownloadImpl.java
new file mode 100644
index 00000000000..ae12c87c699
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/services/s3/transfer/internal/DownloadImpl.java
@@ -0,0 +1,8 @@
+package com.amazonaws.services.s3.transfer.internal;
+
+public class DownloadImpl {
+   public DownloadImpl () {}
+   public Integer getLastFullyDownloadedPartNumber() {
+      return null;
+   }
+}
diff --git a/infer/models/java/src/com/amazonaws/util/CollectionUtils.java b/infer/models/java/src/com/amazonaws/util/CollectionUtils.java
new file mode 100644
index 00000000000..01c58b3bb46
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/util/CollectionUtils.java
@@ -0,0 +1,10 @@
+package com.amazonaws.util;
+
+import java.util.Collection;
+
+public class CollectionUtils {
+
+    public static <T> boolean isNullOrEmpty(Collection<T> collection) {
+        return collection == null || collection.isEmpty();
+    }
+}
diff --git a/infer/models/java/src/com/amazonaws/util/StringUtils.java b/infer/models/java/src/com/amazonaws/util/StringUtils.java
new file mode 100644
index 00000000000..0297e09eb40
--- /dev/null
+++ b/infer/models/java/src/com/amazonaws/util/StringUtils.java
@@ -0,0 +1,8 @@
+package com.amazonaws.util;
+
+public class StringUtils {
+
+  public static boolean isNullOrEmpty(String s) {
+        return s == null || s.length() == 0;
+  }
+}
diff --git a/infer/models/java/src/com/google/common/base/Preconditions.java b/infer/models/java/src/com/google/common/base/Preconditions.java
index f402e9ba0f7..4a4be8bb075 100644
--- a/infer/models/java/src/com/google/common/base/Preconditions.java
+++ b/infer/models/java/src/com/google/common/base/Preconditions.java
@@ -42,18 +42,60 @@ public static void checkState(
     assume(expression);
   }
 
+  public static void checkState(
+      boolean expression,
+      @Nullable String errorMessageTemplate,
+      @Nullable Object errorMessageArg1) {
+    assume(expression);
+  }
+
+  public static void checkState(
+      boolean expression,
+      @Nullable String errorMessageTemplate,
+      @Nullable Object errorMessageArg1,
+      @Nullable Object errorMessageArg2) {
+    assume(expression);
+  }
+
+  public static void checkState(
+      boolean expression,
+      @Nullable String errorMessageTemplate,
+      @Nullable Object errorMessageArg1,
+      @Nullable Object errorMessageArg2,
+      @Nullable Object errorMessageArg3) {
+    assume(expression);
+  }
+
   public static void checkArgument(boolean expression) {
     assume(expression);
   }
 
-  public static void checkArgument(boolean expression, @Nullable Object errorMessage) {
+  public static void checkArgument(boolean expression,
+      @Nullable Object errorMessage) {
     assume(expression);
   }
 
   public static void checkArgument(
       boolean expression,
       @Nullable String errorMessageTemplate,
-      @Nullable Object... errorMessageArgs) {
+      @Nullable Object errorMessageArg1) {
+    assume(expression);
+  }
+
+  public static void checkArgument(
+      boolean expression,
+      @Nullable String errorMessageTemplate,
+      @Nullable Object errorMessageArg1,
+      @Nullable Object errorMessageArg2) {
+    assume(expression);
+  }
+
+  public static void checkArgument(
+      boolean expression,
+      @Nullable String errorMessageTemplate,
+      @Nullable Object errorMessageArg1,
+      @Nullable Object errorMessageArg2,
+      @Nullable Object errorMessageArg3) {
     assume(expression);
   }
 }
diff --git a/infer/models/java/src/java/net/URI.java b/infer/models/java/src/java/net/URI.java
new file mode 100644
index 00000000000..e9a7d3380e2
--- /dev/null
+++ b/infer/models/java/src/java/net/URI.java
@@ -0,0 +1,12 @@
+package java.net;
+
+import static com.facebook.infer.builtins.InferBuiltins.assume;
+import javax.annotation.Nullable;
+
+public final class URI {
+
+  public URI(@Nullable String uri) {
+    assume(uri != null);
+  }
+
+}
diff --git a/infer/models/java/src/java/util/HashMap.java b/infer/models/java/src/java/util/HashMap.java
index 40af20c0e7f..cfbced413f9 100644
--- a/infer/models/java/src/java/util/HashMap.java
+++ b/infer/models/java/src/java/util/HashMap.java
@@ -60,6 +60,19 @@ public V put(K key, V value) {
     return null;
   }
 
+  public V putIfAbsent(K key, V value) {
+    if (value instanceof Closeable) {
+      // assume the resource will be handled correctly in this case
+      InferBuiltins.__set_mem_attribute(value);
+    }
+    pushKey(key);
+
+    if (InferUndefined.boolean_undefined()) {
+      return (V) InferUndefined.object_undefined();
+    }
+    return null;
+  }
+
   public V remove(K key) {
     V value = get(key);
     removeKey(key);
diff --git a/infer/models/java/src/java/util/Objects.java b/infer/models/java/src/java/util/Objects.java
new file mode 100644
index 00000000000..9b62501a91f
--- /dev/null
+++ b/infer/models/java/src/java/util/Objects.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+package java.util;
+
+public abstract class Objects {
+
+  public static boolean isNull(Object obj) {
+    return obj == null;
+  }
+
+  public static boolean nonNull(Object obj) {
+    return obj != null;
+  }
+
+}
diff --git a/infer/models/java/src/junit/framework/Assert.java b/infer/models/java/src/junit/framework/Assert.java
index 4f111ce14e3..2630fd18b35 100644
--- a/infer/models/java/src/junit/framework/Assert.java
+++ b/infer/models/java/src/junit/framework/Assert.java
@@ -8,6 +8,7 @@
 package junit.framework;
 
 import com.facebook.infer.builtins.InferBuiltins;
+import javax.annotation.Nullable;
 
 public class Assert {
 
@@ -26,4 +27,21 @@ public static void assertFalse(boolean condition) {
   public static void assertFalse(String message, boolean condition) {
     InferBuiltins.assume(!condition);
   }
+
+  public static void assertNotNull(@Nullable Object object) {
+    InferBuiltins.assume(object != null);
+  }
+
+  public static void assertNotNull(String message, @Nullable Object object) {
+    InferBuiltins.assume(object != null);
+  }
+
+  public static void assertNull(@Nullable Object object) {
+    InferBuiltins.assume(object == null);
+  }
+
+  public static void assertNull(String message, @Nullable Object object) {
+    InferBuiltins.assume(object == null);
+  }
+
 }
diff --git a/infer/models/java/src/junit/framework/TestCase.java b/infer/models/java/src/junit/framework/TestCase.java
new file mode 100644
index 00000000000..005a95729c2
--- /dev/null
+++ b/infer/models/java/src/junit/framework/TestCase.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+package junit.framework;
+
+import com.facebook.infer.builtins.InferBuiltins;
+import javax.annotation.Nullable;
+
+public class TestCase {
+
+  public static void assertTrue(boolean condition) {
+    InferBuiltins.assume(condition);
+  }
+
+  public static void assertTrue(String message, boolean condition) {
+    InferBuiltins.assume(condition);
+  }
+
+  public static void assertFalse(boolean condition) {
+    InferBuiltins.assume(!condition);
+  }
+
+  public static void assertFalse(String message, boolean condition) {
+    InferBuiltins.assume(!condition);
+  }
+
+  public static void assertNotNull(@Nullable Object object) {
+    InferBuiltins.assume(object != null);
+  }
+
+  public static void assertNotNull(String message, @Nullable Object object) {
+    InferBuiltins.assume(object != null);
+  }
+
+  public static void assertNull(@Nullable Object object) {
+    InferBuiltins.assume(object == null);
+  }
+
+  public static void assertNull(String message, @Nullable Object object) {
+    InferBuiltins.assume(object == null);
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/commons/collections/CollectionUtils.java b/infer/models/java/src/org/apache/commons/collections/CollectionUtils.java
new file mode 100644
index 00000000000..f20f598b9f9
--- /dev/null
+++ b/infer/models/java/src/org/apache/commons/collections/CollectionUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.collections;
+
+import java.util.Collection;
+
+public final class CollectionUtils {
+
+  public static boolean isNotEmpty(final Collection c) {
+    return !isEmpty(c);
+  }
+
+  public static boolean isEmpty(final Collection c) {
+    return c == null || c.size() == 0;
+  }
+
+  public static int size(final Collection c) {
+    return c == null ? 0 : c.size();
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/commons/collections/MapUtils.java b/infer/models/java/src/org/apache/commons/collections/MapUtils.java
new file mode 100644
index 00000000000..d9c3421a011
--- /dev/null
+++ b/infer/models/java/src/org/apache/commons/collections/MapUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.collections;
+
+import java.util.Map;
+
+public final class MapUtils {
+
+  public static boolean isNotEmpty(final Map m) {
+    return !isEmpty(m);
+  }
+
+  public static boolean isEmpty(final Map m) {
+    return m == null;
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/commons/collections4/CollectionUtils.java b/infer/models/java/src/org/apache/commons/collections4/CollectionUtils.java
new file mode 100644
index 00000000000..823ff27cf2d
--- /dev/null
+++ b/infer/models/java/src/org/apache/commons/collections4/CollectionUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.collections4;
+
+import java.util.Collection;
+
+public final class CollectionUtils {
+
+  public static boolean isNotEmpty(final Collection c) {
+    return !isEmpty(c);
+  }
+
+  public static boolean isEmpty(final Collection c) {
+    return c == null || c.size() == 0;
+  }
+
+  public static int size(final Collection c) {
+    return c == null ? 0 : c.size();
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/commons/collections4/MapUtils.java b/infer/models/java/src/org/apache/commons/collections4/MapUtils.java
new file mode 100644
index 00000000000..fc1433a3cc0
--- /dev/null
+++ b/infer/models/java/src/org/apache/commons/collections4/MapUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.collections4;
+
+import java.util.Map;
+
+public final class MapUtils {
+
+  public static boolean isNotEmpty(final Map m) {
+    return !isEmpty(m);
+  }
+
+  public static boolean isEmpty(final Map m) {
+    return m == null;
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/commons/lang/StringUtils.java b/infer/models/java/src/org/apache/commons/lang/StringUtils.java
new file mode 100644
index 00000000000..716bdd18a11
--- /dev/null
+++ b/infer/models/java/src/org/apache/commons/lang/StringUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* 
+ * The method below are copied verbatim from:
+ * https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java
+ * to provide a model for biabduction analysis
+ */
+
+package org.apache.commons.lang;
+
+public final class StringUtils {
+
+  public static boolean isNotEmpty(final String cs) {
+    return !isEmpty(cs);
+  }
+
+  public static boolean isNotBlank(final String cs) {
+    return !isBlank(cs);
+  }
+
+  public static boolean isEmpty(final String cs) {
+    return cs == null || cs.length() == 0;
+  }
+
+  public static boolean isBlank(final String cs) {
+    return isEmpty(cs);
+  }
+
+  public static int length(final String cs) {
+    return cs == null ? 0 : cs.length();
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/commons/lang3/StringUtils.java b/infer/models/java/src/org/apache/commons/lang3/StringUtils.java
index 38a7c521214..0ce95a96291 100644
--- a/infer/models/java/src/org/apache/commons/lang3/StringUtils.java
+++ b/infer/models/java/src/org/apache/commons/lang3/StringUtils.java
@@ -29,6 +29,10 @@ public static boolean isNotEmpty(final CharSequence cs) {
     return !isEmpty(cs);
   }
 
+  public static boolean isNotBlank(final CharSequence cs) {
+    return !isBlank(cs);
+  }
+
   public static boolean isEmpty(final CharSequence cs) {
     return cs == null || cs.length() == 0;
   }
diff --git a/infer/models/java/src/org/apache/commons/lang3/Validate.java b/infer/models/java/src/org/apache/commons/lang3/Validate.java
new file mode 100644
index 00000000000..555dd2db71d
--- /dev/null
+++ b/infer/models/java/src/org/apache/commons/lang3/Validate.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.lang3;
+
+import static com.facebook.infer.builtins.InferBuiltins.assume;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import java.util.Collection;
+import java.util.Map;
+
+public class Validate {
+
+   public static <T> T notNull(T object) {
+     assume(object != null);
+     return object;
+   }
+
+   public static <T> T notNull(T object, String message, Object... values) {
+     assume(object != null);
+     return object;
+   }
+
+   public static <T extends CharSequence> T notEmpty(T chars) {
+     assume(chars != null && chars.length() > 0 );
+     return chars;
+   }
+
+   public static <T extends CharSequence> T notBlank(T chars) {
+     assume(chars != null && chars.length() > 0 );
+     return chars;
+   }
+
+   public static <T extends CharSequence> T notEmpty(T chars, String message, Object... values) {
+     return notEmpty(chars);
+   }
+
+   public static <T extends CharSequence> T notBlank(T chars, String message, Object... values) {
+     return notBlank(chars);
+   }
+
+   public static <T extends Collection<?>> T notEmpty(T collection) {
+     assume(collection != null && collection.size() > 0 );
+     return collection;
+   }
+
+   public static <T extends Collection<?>> T notEmpty(T collection, String message, Object... values) {
+     return notEmpty(collection);
+  }
+
+  public static <T extends Map<?,?>> T notEmpty(T map) {
+     assume(map != null);
+    return map;
+  }
+
+  public static <T extends Map<?,?>> T notEmpty(T map, String message, Object... values) {
+     return notEmpty(map);
+  }
+
+  public static void isTrue(boolean expression) {
+     assume(expression);
+  }
+
+  public static void isTrue(boolean expression, String message, double value) {
+     assume(expression);
+  }
+
+  public static void isTrue(boolean expression, String message, long value) {
+     assume(expression);
+  }
+
+  public static void isTrue(boolean expression, String message, Object... values) {
+     assume(expression);
+  }
+
+}
diff --git a/infer/models/java/src/org/apache/logging/log4j/util/Strings.java b/infer/models/java/src/org/apache/logging/log4j/util/Strings.java
new file mode 100644
index 00000000000..5a1101136a6
--- /dev/null
+++ b/infer/models/java/src/org/apache/logging/log4j/util/Strings.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.logging.log4j.util;
+
+public final class Strings {
+
+  public static boolean isNotEmpty(final String cs) {
+    return !isEmpty(cs);
+  }
+
+  public static boolean isNotBlank(final String cs) {
+    return !isBlank(cs);
+  }
+
+  public static boolean isEmpty(final String cs) {
+    return cs == null || cs.length() == 0;
+  }
+
+  public static boolean isBlank(final String cs) {
+    return isEmpty(cs);
+  }
+
+}
diff --git a/infer/models/java/src/org/junit/Assert.java b/infer/models/java/src/org/junit/Assert.java
new file mode 100644
index 00000000000..5369e095f6c
--- /dev/null
+++ b/infer/models/java/src/org/junit/Assert.java
@@ -0,0 +1,24 @@
+package org.junit;
+
+import static com.facebook.infer.builtins.InferBuiltins.assume;
+import javax.annotation.Nullable;
+
+public class Assert {
+
+  public static void assertNotNull(@Nullable Object object) {
+    assume(object != null);
+  }
+
+  public static void assertNotNull(String message, @Nullable Object object) {
+    assume(object != null);
+  }
+
+  public static void assertNull(@Nullable Object object) {
+    assume(object == null);
+  }
+
+  public static void assertNull(String message, @Nullable Object object) {
+    assume(object == null);
+  }
+
+}
diff --git a/infer/models/java/src/org/junit/jupiter/api/Assertions.java b/infer/models/java/src/org/junit/jupiter/api/Assertions.java
new file mode 100644
index 00000000000..b6ae50890b2
--- /dev/null
+++ b/infer/models/java/src/org/junit/jupiter/api/Assertions.java
@@ -0,0 +1,24 @@
+package org.junit.jupiter.api;
+
+import static com.facebook.infer.builtins.InferBuiltins.assume;
+import javax.annotation.Nullable;
+
+public class Assertions {
+
+  public static void assertNotNull(@Nullable Object object) {
+    assume(object != null);
+  }
+
+  public static void assertNotNull(@Nullable Object object, String message) {
+    assume(object != null);
+  }
+
+  public static void assertNull(@Nullable Object object) {
+    assume(object == null);
+  }
+
+  public static void assertNull(@Nullable Object object, String message) {
+    assume(object == null);
+  }
+
+}
diff --git a/infer/models/java/src/org/springframework/util/CollectionUtils.java b/infer/models/java/src/org/springframework/util/CollectionUtils.java
new file mode 100644
index 00000000000..74d32c2a374
--- /dev/null
+++ b/infer/models/java/src/org/springframework/util/CollectionUtils.java
@@ -0,0 +1,15 @@
+package org.springframework.util;
+
+import java.util.Collection;
+import java.util.Map;
+
+public final class CollectionUtils {
+
+  public static boolean isEmpty(final Collection c) {
+    return c == null || c.size() == 0;
+  }
+
+  public static boolean isEmpty(final Map m) {
+    return m == null;
+  }
+}
diff --git a/infer/models/java/src/org/testng/Assert.java b/infer/models/java/src/org/testng/Assert.java
new file mode 100644
index 00000000000..6aee3c4175f
--- /dev/null
+++ b/infer/models/java/src/org/testng/Assert.java
@@ -0,0 +1,24 @@
+package org.testng;
+
+import static com.facebook.infer.builtins.InferBuiltins.assume;
+import javax.annotation.Nullable;
+
+public class Assert {
+
+  public static void assertNotNull(@Nullable Object object) {
+    assume(object != null);
+  }
+
+  public static void assertNotNull(@Nullable Object object, String message) {
+    assume(object != null);
+  }
+
+  public static void assertNull(@Nullable Object object) {
+    assume(object == null);
+  }
+
+  public static void assertNull(@Nullable Object object, String message) {
+    assume(object == null);
+  }
+
+}
diff --git a/infer/models/java/src/org/testng/AssertJUnit.java b/infer/models/java/src/org/testng/AssertJUnit.java
new file mode 100644
index 00000000000..d7355db7c1d
--- /dev/null
+++ b/infer/models/java/src/org/testng/AssertJUnit.java
@@ -0,0 +1,24 @@
+package org.testng;
+
+import static com.facebook.infer.builtins.InferBuiltins.assume;
+import javax.annotation.Nullable;
+
+public class AssertJUnit {
+
+  public static void assertNotNull(@Nullable Object object) {
+    assume(object != null);
+  }
+
+  public static void assertNotNull(String message, @Nullable Object object) {
+    assume(object != null);
+  }
+
+  public static void assertNull(@Nullable Object object) {
+    assume(object == null);
+  }
+
+  public static void assertNull(String message, @Nullable Object object) {
+    assume(object == null);
+  }
+
+}
diff --git a/infer/src/nullsafe/modelTables.ml b/infer/src/nullsafe/modelTables.ml
index dbfdc75bb60..2e7a7400924 100644
--- a/infer/src/nullsafe/modelTables.ml
+++ b/infer/src/nullsafe/modelTables.ml
@@ -150,7 +150,79 @@ let check_not_null_parameter_list, check_not_null_list =
     ; ( 1
       , (o, [n; n])
       , "androidx.core.util.Preconditions.checkNotNull(java.lang.Object,java.lang.Object):java.lang.Object"
-      ) ]
+      )
+    ; ( 1
+      , (o, [n])
+      , "java.util.Objects.requireNonNull(java.lang.Object):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "java.util.Objects.requireNonNull(java.lang.Object, java.lang.String):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "java.util.Objects.requireNonNull(java.lang.Object, java.util.function.Supplier):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang3.Validate.notNull(java.lang.Object):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang3.Validate.notNull(java.lang.Object,java.lang.String):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang3.Validate.notNull(java.lang.Object,java.lang.String,java.lang.Object):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang3.Validate.notEmpty(java.util.Collection):java.util.Collection"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "org.apache.commons.lang3.Validate.notEmpty(java.util.Collection,java.lang.String):java.util.Collection"
+      )
+    ; ( 1
+      , (o, [n; n; n])
+      , "org.apache.commons.lang3.Validate.notEmpty(java.util.Collection,java.lang.String,java.lang.Object):java.util.Collection"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang3.Validate.notEmpty(java.lang.CharSequence):java.lang.CharSequence"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "org.apache.commons.lang3.Validate.notEmpty(java.lang.CharSequence,java.lang.String):java.lang.CharSequence"
+      )
+    ; ( 1
+      , (o, [n; n; n])
+      , "org.apache.commons.lang3.Validate.notEmpty(java.lang.CharSequence,java.lang.String,java.lang.Object):java.lang.CharSequence"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang.Validate.notNull(java.lang.Object):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "org.apache.commons.lang.Validate.notNull(java.lang.Object,java.lang.String):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang.Validate.notEmpty(java.util.Collection):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "org.apache.commons.lang.Validate.notEmpty(java.util.Collection,java.lang.String):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n])
+      , "org.apache.commons.lang.Validate.notEmpty(java.lang.CharSequence):java.lang.Object"
+      )
+    ; ( 1
+      , (o, [n; n])
+      , "org.apache.commons.lang.Validate.notEmpty(java.lang.CharSequence,java.lang.String):java.lang.Object"
+      )]
   in
   (List.map ~f:(fun (x, _, z) -> (x, z)) list, List.map ~f:(fun (_, y, z) -> (y, z)) list)
 
@@ -207,8 +279,12 @@ let check_argument_list =
 (** Models for boolean functions that return true on null. *)
 let true_on_null_list =
   [ (n1, "android.text.TextUtils.isEmpty(java.lang.CharSequence):boolean")
-  ; (n1, "com.google.common.base.Strings.isNullOrEmpty(java.lang.String):boolean") ]
+  ; (n1, "com.google.common.base.Strings.isNullOrEmpty(java.lang.String):boolean")
+  ; (n1, "java.util.Objects.isNull(java.lang.Object):boolean") ] 
 
+(** Models for boolean functions that return false on null. *)
+let false_on_null_list =
+  [ (n1, "java.util.Objects.nonNull(java.lang.Object):boolean") ] 
 
 (** Models for Map.containsKey *)
 let containsKey_list =
@@ -706,6 +782,8 @@ let noreturn_table = mk_table noreturn_list
 
 let true_on_null_table = mk_table true_on_null_list
 
+let false_on_null_table = mk_table false_on_null_list
+
 let nonnull_alternatives_table =
   let method_descr_to_alternative =
     List.map nullable_methods_with_nonnull_alternatives_list
diff --git a/infer/src/nullsafe/modelTables.mli b/infer/src/nullsafe/modelTables.mli
index c4e738349ea..1cdb82fcd9d 100644
--- a/infer/src/nullsafe/modelTables.mli
+++ b/infer/src/nullsafe/modelTables.mli
@@ -35,6 +35,8 @@ val noreturn_table : model_table_t
 
 val true_on_null_table : model_table_t
 
+val false_on_null_table : model_table_t
+
 (** Used to describe a method complementary to a given one. Contains information needed for
     reporting (hence does not describe the whole signature). *)
 type nonnull_alternative_method = {package_name: string; class_name: string; method_name: string}
diff --git a/infer/src/nullsafe/models.ml b/infer/src/nullsafe/models.ml
index b1cca9cedab..f5732cc208e 100644
--- a/infer/src/nullsafe/models.ml
+++ b/infer/src/nullsafe/models.ml
@@ -120,7 +120,7 @@ let is_false_on_null proc_name =
   (* The only usecase for now - consider all overrides of `Object.equals()` correctly
      implementing the Java specification contract (returning false on null). *)
   PatternMatch.Java.is_override_of_lang_object_equals (Procname.Java proc_name)
-
+   ||  table_has_procedure false_on_null_table proc_name
 
 let is_containsKey proc_name = table_has_procedure containsKey_table proc_name
 
diff --git a/infer/tests/base.make b/infer/tests/base.make
index bfa00bffbe7..a8965d0ccd7 100644
--- a/infer/tests/base.make
+++ b/infer/tests/base.make
@@ -26,7 +26,7 @@ endef
 
 define check_no_diff
   git --no-pager diff --color=auto --no-ext-diff --no-index --word-diff --unified=1 --minimal \
-	$$(realpath $(1)) $$(realpath $(2)) >&2 || \
+	$$(/Users/cottet/infer/infer/bin/realpath $(1)) $$(/Users/cottet/infer/infer/bin/realpath $(2)) >&2 || \
   (printf '\n' >&2; \
    printf '$(TERM_ERROR)Test output ($(2)) differs from expected test output $(1)$(TERM_RESET)\n' >&2; \
    printf '$(TERM_ERROR)Run the following command to replace the expected test output with the new output:$(TERM_RESET)\n' >&2; \
diff --git a/infer/tests/codetoanalyze/java/biabduction/NullPointerExceptions.java b/infer/tests/codetoanalyze/java/biabduction/NullPointerExceptions.java
index 0dceefb77c7..abd29c95cd6 100644
--- a/infer/tests/codetoanalyze/java/biabduction/NullPointerExceptions.java
+++ b/infer/tests/codetoanalyze/java/biabduction/NullPointerExceptions.java
@@ -13,6 +13,7 @@
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.text.TextUtils;
+import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
 import com.facebook.infer.annotation.Assertions;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -27,6 +28,16 @@
 import java.util.concurrent.locks.Lock;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import java.util.Objects;
+import java.util.Map;
+import java.util.List;
+import junit.framework.TestCase;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.testng.Assert;
+import org.testng.AssertJUnit;
 
 public class NullPointerExceptions {
 
@@ -180,6 +191,11 @@ String NPEhashmapProtectedByContainsKey(HashMap h, Object o) {
     return "aa";
   }
 
+  String NPEhashmapProtectedByPut(HashMap h, Object o) {
+    h.put(o, o);
+    return (h.get(o).toString());
+  }
+
   int NPEvalueOfFromHashmapBad(HashMap<Integer, Integer> h, int position) {
     return h.get(position);
   }
@@ -634,4 +650,193 @@ void addNullToImmutableListBuilderBad() {
     ImmutableList.Builder<Object> listBuilder = ImmutableList.builder();
     listBuilder.add(getObject());
   }
+
+  String requireNonNullOk(@Nullable Object object) {
+    return Objects.requireNonNull(object).toString();
+  }
+
+  String objectsNonNullOk(@Nullable Object object) {
+    if (!Objects.isNull(object)) {
+      return object.toString();
+    }
+    return null;
+  }
+
+  String assertNotNullOK(@Nullable Object object) {
+    Assert.assertNotNull(object);
+    return object.toString();
+  }
+
+  String assertJUnitNotNullOK(@Nullable Object object) {
+    AssertJUnit.assertNotNull(object);
+    return object.toString();
+  }
+
+  String junitAssertNotNullOK(@Nullable Object object) {
+    org.junit.Assert.assertNotNull(object);
+    return object.toString();
+  }
+
+  String junitTestCaseNotNullOK(@Nullable Object object) {
+    TestCase.assertNotNull(object);
+    return object.toString();
+  }
+
+  String jupiterAssertionsNotNullOK(@Nullable Object object) {
+    org.junit.jupiter.api.Assertions.assertNotNull(object);
+    return object.toString();
+  }
+
+  String uriOK(@Nullable String str) throws java.net.URISyntaxException {
+    java.net.URI uri = new java.net.URI(str);
+    return str.toLowerCase();
+  }
+
+  String stringUtilsIsNotEmptyOk(@Nullable String str) {
+    if (StringUtils.isNotEmpty(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String stringUtilsIsNotBlankOk(@Nullable String str) {
+    if (StringUtils.isNotBlank(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String stringsIsNotEmptyOk(@Nullable String str) {
+    if (org.apache.logging.log4j.util.Strings.isNotEmpty(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String stringsIsNotBlankOk(@Nullable String str) {
+    if (org.apache.logging.log4j.util.Strings.isNotBlank(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String stringUtils3IsNotBlankOk(@Nullable String str) {
+    if (org.apache.commons.lang3.StringUtils.isNotBlank(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String stringUtils3IsNotEmptyOk(@Nullable String str) {
+    if (org.apache.commons.lang3.StringUtils.isNotEmpty(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String collectionUtilsIsNotEmptyOk(@Nullable List list) {
+    if (CollectionUtils.isNotEmpty(list)) {
+       return list.toString();
+    }
+    return null;
+  }
+
+  String collectionUtilsIsEmptyOk(@Nullable List list) {
+    if (!CollectionUtils.isEmpty(list)) {
+       return list.toString();
+    }
+    return null;
+  }
+
+  String springFrameworkCollectionUtilsIsEmptyOk(@Nullable List list) {
+    if (!org.springframework.util.CollectionUtils.isEmpty(list)) {
+       return list.toString();
+    }
+    return null;
+  }
+
+  String collectionUtils4IsNotEmptyOk(@Nullable List list) {
+    if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)) {
+       return list.toString();
+    }
+    return null;
+  }
+
+  String mapUtilsIsNotEmptyOk(@Nullable Map map) {
+    if (MapUtils.isNotEmpty(map)) {
+       return map.toString();
+    }
+    return null;
+  }
+
+  String mapUtils4IsNotEmptyOk(@Nullable Map map) {
+    if (org.apache.commons.collections4.MapUtils.isNotEmpty(map)) {
+       return map.toString();
+    }
+    return null;
+  }
+
+  String validateNotNullOK(@Nullable Object obj) {
+    return Validate.notNull(obj).toString();
+  }
+
+  String validateNotNullOK(@Nullable String str) {
+    return Validate.notEmpty(str).toLowerCase();
+  }
+
+  String validateNotEmptyOK(@Nullable List list) {
+    return Validate.notEmpty(list).toString();
+  }
+
+  String validateNotEmptyOK(@Nullable Map map) {
+    return Validate.notEmpty(map).toString();
+  }
+
+  String validateIsTrue(@Nullable Object obj) {
+    Validate.isTrue(obj != null);
+    return obj.toString();
+  }
+
+  String stringUtilsIsNullOrEmptyOK(@Nullable String str) {
+    if (!com.amazonaws.util.StringUtils.isNullOrEmpty(str)) {
+       return str.toLowerCase();
+    }
+    return null;
+  }
+
+  String collectionUtilsIsNullOrEmptyOK(@Nullable List list) {
+    if (!com.amazonaws.util.CollectionUtils.isNullOrEmpty(list)) {
+       return list.toString();
+    }
+    return null;
+  }
+
+  String dynamodbMapperWarning2() {
+    DynamoDBMapper mapper = new DynamoDBMapper();
+    Float object2 = 1.0f;
+    Object object = mapper.load(Object.class, object2);
+    return object.toString();
+  }
+
+  void dynamodbMapperWarning3() {
+    DynamoDBMapper mapper = new DynamoDBMapper();
+    String object2 = "foo";
+    NullPointerExceptions object = mapper.load(NullPointerExceptions.class, object2);
+    object.toString();
+  }
+
+  String preconditionCheckArgumentTest(@Nullable Object obj) {
+    Preconditions.checkArgument(Objects.nonNull(obj));
+    return obj.toString();
+  }
+
+  String preconditionCheckArgumentDescriptionTest(@Nullable Object obj) {
+    Preconditions.checkArgument(Objects.nonNull(obj), "obj is null");
+    return obj.toString();
+  }
+
+  String preconditionCheckArgumentDescriptionParameterTest(@Nullable Object obj) {
+    Preconditions.checkArgument(Objects.nonNull(obj), "obj is null %s ", new String("foo"));
+    return obj.toString();
+  }
 }
diff --git a/infer/tests/codetoanalyze/java/biabduction/issues.exp b/infer/tests/codetoanalyze/java/biabduction/issues.exp
index 5d72f5bbfa9..4cbf42edbcc 100644
--- a/infer/tests/codetoanalyze/java/biabduction/issues.exp
+++ b/infer/tests/codetoanalyze/java/biabduction/issues.exp
@@ -106,6 +106,8 @@ codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.in
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.dereferenceAfterLoopOnList(codetoanalyze.java.infer.NullPointerExceptions$L):void, 2, NULL_DEREFERENCE, B2, ERROR, [start of procedure dereferenceAfterLoopOnList(...),start of procedure returnsNullAfterLoopOnList(...),Taking true branch,Taking true branch,Taking false branch,return from a call to Object NullPointerExceptions.returnsNullAfterLoopOnList(NullPointerExceptions$L)]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.dereferenceAfterUnlock1(java.util.concurrent.locks.Lock):void, 4, NULL_DEREFERENCE, B1, ERROR, [start of procedure dereferenceAfterUnlock1(...),Skipping toString(): unknown method]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.dereferenceAfterUnlock2(java.util.concurrent.locks.Lock):void, 6, NULL_DEREFERENCE, B1, ERROR, [start of procedure dereferenceAfterUnlock2(...),Skipping toString(): unknown method]
+codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.dynamodbMapperWarning2():java.lang.String, 4, NULL_DEREFERENCE, B1, ERROR, [start of procedure dynamodbMapperWarning2(),Skipping valueOf(...): unknown method]
+codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.dynamodbMapperWarning3():void, 4, NULL_DEREFERENCE, B1, ERROR, [start of procedure dynamodbMapperWarning3()]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.hashmapNPE(java.util.HashMap,java.lang.Object):java.lang.String, 1, NULL_DEREFERENCE, B2, ERROR, [start of procedure hashmapNPE(...)]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.nullDerefernceReturnOfSkippedFunctionBad():void, 3, NULL_DEREFERENCE, B1, ERROR, [start of procedure nullDerefernceReturnOfSkippedFunctionBad(),Skipping unknownFunc(): unknown method,Definition of unknownFunc(),Taking true branch]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.nullListFiles(java.lang.String):int, 3, NULL_DEREFERENCE, B1, ERROR, [start of procedure nullListFiles(...),Skipping File(...): unknown method]
@@ -126,6 +128,9 @@ codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.in
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.nullableFieldNPE():void, 1, NULL_DEREFERENCE, B1, ERROR, [start of procedure nullableFieldNPE()]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.nullableParamNPE(java.lang.Object):void, 1, NULL_DEREFERENCE, B1, ERROR, [start of procedure nullableParamNPE(...)]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.optionalNPE(com.google.common.base.Optional):void, 1, NULL_DEREFERENCE, B2, ERROR, [start of procedure optionalNPE(...)]
+codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.preconditionCheckArgumentDescriptionParameterTest(java.lang.Object):java.lang.String, 1, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure preconditionCheckArgumentDescriptionParameterTest(...)]
+codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.preconditionCheckArgumentDescriptionTest(java.lang.Object):java.lang.String, 1, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure preconditionCheckArgumentDescriptionTest(...)]
+codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.preconditionCheckArgumentTest(java.lang.Object):java.lang.String, 1, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure preconditionCheckArgumentTest(...)]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.preconditionCheckStateTest(codetoanalyze.java.infer.NullPointerExceptions$D):int, 1, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure preconditionCheckStateTest(...),Taking false branch]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.someNPEAfterResourceLeak():void, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure someNPEAfterResourceLeak(),start of procedure sourceOfNullWithResourceLeakBad(),start of procedure SomeResource(),return from a call to SomeResource.<init>(),return from a call to T CloseableAsResourceExample.sourceOfNullWithResourceLeakBad()]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.stringConstantEqualsFalseNotNPE_FP():void, 10, NULL_DEREFERENCE, B1, ERROR, [start of procedure stringConstantEqualsFalseNotNPE_FP(),Taking false branch]
@@ -133,6 +138,7 @@ codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.in
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.testSystemGetPropertyArgument():java.lang.String, 1, NULL_DEREFERENCE, B1, ERROR, [start of procedure testSystemGetPropertyArgument()]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.testSystemGetPropertyReturn():void, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure testSystemGetPropertyReturn()]
 codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.tryLockThrows(java.nio.channels.FileChannel):java.lang.String, 6, NULL_DEREFERENCE, B1, ERROR, [start of procedure tryLockThrows(...),exception java.io.IOException,Switch condition is true. Entering switch case]
+codetoanalyze/java/biabduction/NullPointerExceptions.java, codetoanalyze.java.infer.NullPointerExceptions.validateIsTrue(java.lang.Object):java.lang.String, 1, PRECONDITION_NOT_MET, no_bucket, WARNING, [start of procedure validateIsTrue(...),Taking false branch]
 codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.bufferedReaderNotClosedAfterRead():void, 6, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure bufferedReaderNotClosedAfterRead(),exception java.io.IOException]
 codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.fileReaderNotClosedAfterRead():void, 6, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure fileReaderNotClosedAfterRead(),Skipping FileReader(...): unknown method,exception java.io.IOException]
 codetoanalyze/java/biabduction/ReaderLeaks.java, codetoanalyze.java.infer.ReaderLeaks.inputStreamReaderNotClosedAfterRead():void, 6, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure inputStreamReaderNotClosedAfterRead(),Skipping InputStreamReader(...): unknown method,exception java.io.IOException]
diff --git a/infer/tests/codetoanalyze/java/nullsafe/NullLibraries.java b/infer/tests/codetoanalyze/java/nullsafe/NullLibraries.java
new file mode 100644
index 00000000000..501bc82dc29
--- /dev/null
+++ b/infer/tests/codetoanalyze/java/nullsafe/NullLibraries.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+package codetoanalyze.java.nullsafe;;
+
+import java.util.Objects;
+import java.util.Collection;
+import javax.annotation.Nullable;
+import lombok.NonNull;
+import org.apache.commons.lang3.Validate;
+
+public class NullLibraries {
+
+  void objectsNonNullOK(@Nullable Object object) {
+    if (Objects.nonNull(object)) {
+      object.toString();
+    }
+  }
+
+  void objectsNonNullWarn(@Nullable Object object) {
+    if (! Objects.nonNull(object)) {
+      object.toString();
+    }
+  }
+
+  void objectsIsNullWarn(@Nullable Object object) {
+    if (Objects.isNull(object)) {
+      object.toString();
+    }
+  }
+
+  void objectsIsNullOK(@Nullable Object object) {
+    if (!Objects.isNull(object)) {
+      object.toString();
+    }
+  }
+
+  void objectsRequireNonNullOK(@Nullable Object object) {
+    Objects.requireNonNull(object);
+    object.toString();
+  }
+
+  void objectsCommons3ValidateNotNullOK(@Nullable Object object) {
+    Validate.notNull(object);
+    object.toString();
+  }
+
+  void objectsCommons3ValidateNotEmptyOK(@Nullable Collection collection) {
+    Validate.notEmpty(collection);
+    collection.toString();
+  }
+
+  void objectsLombokNonNullOK(@NonNull @Nullable Object object) {
+    object.toString();
+  }
+
+}
diff --git a/infer/tests/codetoanalyze/java/nullsafe/NullMethodCall.java b/infer/tests/codetoanalyze/java/nullsafe/NullMethodCall.java
index 55b844a04ba..ccdb1598943 100644
--- a/infer/tests/codetoanalyze/java/nullsafe/NullMethodCall.java
+++ b/infer/tests/codetoanalyze/java/nullsafe/NullMethodCall.java
@@ -366,4 +366,5 @@ String testNotDetectingInvariantFP(@Nullable Object object1, @Nullable Object ob
     }
     return object1 == null ? object2.toString() : "null";
   }
+
 }
diff --git a/infer/tests/codetoanalyze/java/nullsafe/issues.exp b/infer/tests/codetoanalyze/java/nullsafe/issues.exp
index a7fb2560145..0341579d792 100644
--- a/infer/tests/codetoanalyze/java/nullsafe/issues.exp
+++ b/infer/tests/codetoanalyze/java/nullsafe/issues.exp
@@ -191,6 +191,9 @@ codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe.Nu
 codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe.NullFieldAccess.testInterface():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`bad` is nullable and is not locally checked for null when calling `toString()`: field nullable at line 52.], NullFieldAccess, codetoanalyze.java.nullsafe
 codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe.NullFieldAccess.testNonStaticFields():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`bad` is nullable and is not locally checked for null when calling `toString()`: field nullable at line 36.], NullFieldAccess, codetoanalyze.java.nullsafe
 codetoanalyze/java/nullsafe/NullFieldAccess.java, codetoanalyze.java.nullsafe.NullFieldAccess.testStatic():void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`bad` is nullable and is not locally checked for null when calling `toString()`: field nullableStatic at line 44.], NullFieldAccess, codetoanalyze.java.nullsafe
+codetoanalyze/java/nullsafe/NullLibraries.java, Linters_dummy_method, 16, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullLibraries, codetoanalyze.java.nullsafe, issues: 2, curr_mode: "Default"
+codetoanalyze/java/nullsafe/NullLibraries.java, codetoanalyze.java.nullsafe.NullLibraries.objectsIsNullWarn(java.lang.Object):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`object` is nullable and is not locally checked for null when calling `toString()`.], NullLibraries, codetoanalyze.java.nullsafe
+codetoanalyze/java/nullsafe/NullLibraries.java, codetoanalyze.java.nullsafe.NullLibraries.objectsNonNullWarn(java.lang.Object):void, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`object` is nullable and is not locally checked for null when calling `toString()`.], NullLibraries, codetoanalyze.java.nullsafe
 codetoanalyze/java/nullsafe/NullMethodCall.java, Linters_dummy_method, 22, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullMethodCall, codetoanalyze.java.nullsafe, issues: 23, curr_mode: "Default"
 codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe.NullMethodCall$Inner.outerField():int, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s` is nullable and is not locally checked for null when calling `length()`: field fld at line 69.], NullMethodCall$Inner, codetoanalyze.java.nullsafe
 codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe.NullMethodCall$Inner.outerPrivateField():int, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`s` is nullable and is not locally checked for null when calling `length()`: field pfld at line 80.], NullMethodCall$Inner, codetoanalyze.java.nullsafe
diff --git a/infer/tests/java.make b/infer/tests/java.make
index 875507af03d..7b361cb0a46 100644
--- a/infer/tests/java.make
+++ b/infer/tests/java.make
@@ -17,5 +17,9 @@ JACKSON = $(DEPENDENCIES_DIR)/java/jackson/jackson-2.2.3.jar
 JSR305 = $(DEPENDENCIES_DIR)/java/jsr-305/jsr305.jar
 KOTLIN_ANNOTATIONS = $(DEPENDENCIES_DIR)/java/kotlin-annotations/kotlin-annotations-jvm-1.3.72.jar
 SUNTOOLS = $(DEPENDENCIES_DIR)/java/sun-tools/tools.jar
+COMMONS_JAR = $(DEPENDENCIES_DIR)/java/commons/commons-lang-2.6.jar
+COMMONS3_JAR = $(DEPENDENCIES_DIR)/java/commons/commons-lang3-3.0.jar
+LOMBOK_JAR = $(DEPENDENCIES_DIR)/java/lombok/lombok-1.18.20.jar
+MODELS_JAR = $(ROOT_DIR)/infer/models/models.jar
 
-CLASSPATH=$(ANDROID):$(ANDROIDX_COLLECTION):$(ANDROIDSUPPORT):$(ANNOTATIONS):$(GUAVA):$(JACKSON):$(JSR305):$(INJECT):$(KOTLIN_ANNOTATIONS):$(SUNTOOLS):$(JAVA_BUILTINS_DIR):$(TEST_CLASSPATH):.
+CLASSPATH=$(ANDROID):$(ANDROIDX_COLLECTION):$(ANDROIDSUPPORT):$(ANNOTATIONS):$(GUAVA):$(JACKSON):$(JSR305):$(INJECT):$(KOTLIN_ANNOTATIONS):$(SUNTOOLS):$(COMMONS_JAR):$(COMMONS3_JAR):$(LOMBOK_JAR):$(JAVA_BUILTINS_DIR):$(TEST_CLASSPATH):$(MODELS_JAR):.