diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
index 1013dc698cd6f0..87c973f941c280 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaConfiguration.java
@@ -235,6 +235,16 @@ public boolean getUseIjars() {
     return useIjars;
   }
 
+  /**
+   * Returns true iff Java compilation should use ijars. Checks if the functions is been called from
+   * builtins.
+   */
+  @Override
+  public boolean getUseIjarsInStarlark(StarlarkThread thread) throws EvalException {
+    checkPrivateAccess(thread);
+    return useIjars;
+  }
+
   /** Returns true iff Java header compilation is enabled. */
   public boolean useHeaderCompilation() {
     return useHeaderCompilation;
@@ -278,7 +288,7 @@ public String getFixDepsTool() {
     return fixDepsTool;
   }
 
-  /** @return proper label only if --java_launcher= is specified, otherwise null. */
+  /** Returns proper label only if --java_launcher= is specified, otherwise null. */
   @StarlarkConfigurationField(
       name = "launcher",
       doc = "Returns the label provided with --java_launcher, if any.",
@@ -397,6 +407,14 @@ public boolean getDisallowJavaImportEmptyJarsInStarlark(StarlarkThread thread)
     return disallowJavaImportEmptyJars;
   }
 
+  /** Returns true if java_import exports are not allowed. */
+  @Override
+  public boolean getDisallowJavaImportExportsInStarlark(StarlarkThread thread)
+      throws EvalException {
+    checkPrivateAccess(thread);
+    return disallowJavaImportExports;
+  }
+
   @Override
   public String starlarkOneVersionEnforcementLevel() {
     return oneVersionEnforcementLevel().name();
diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
index 7b723ed0c5a921..c2ed988a889437 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaToolchainProvider.java
@@ -267,7 +267,7 @@ public Label getToolchainLabel() {
     return label;
   }
 
-  /** @return the target Java bootclasspath */
+  /** Returns the target Java bootclasspath. */
   public BootClassPathInfo getBootclasspath() {
     return bootclasspath;
   }
@@ -325,7 +325,6 @@ public ImmutableSet<String> getReducedClasspathIncompatibleProcessors() {
     return reducedClasspathIncompatibleProcessors;
   }
 
-
   /**
    * Returns {@code true} if header compilation should be forcibly disabled, overriding
    * --java_header_compilation.
@@ -374,6 +373,12 @@ public Artifact depsChecker() {
     return depsChecker;
   }
 
+  @Override
+  public Artifact getDepsCheckerForStarlark(StarlarkThread thread) throws EvalException {
+    checkPrivateAccess(thread);
+    return depsChecker();
+  }
+
   @Nullable
   public Artifact getResourceJarBuilder() {
     return resourceJarBuilder;
@@ -397,12 +402,12 @@ ImmutableListMultimap<String, String> getCompatibleJavacOptions() {
     return compatibleJavacOptions;
   }
 
-  /** @return the map of target environment-specific javacopts. */
+  /** Returns the map of target environment-specific javacopts. */
   public ImmutableList<String> getCompatibleJavacOptions(String key) {
     return getCompatibleJavacOptions().get(key);
   }
 
-  /** @return the list of default options for the java compiler */
+  /** Returns the list of default options for the java compiler. */
   public ImmutableList<String> getJavacOptions(RuleContext ruleContext) {
     ImmutableList.Builder<String> result = ImmutableList.<String>builder().addAll(javacOptions);
     if (ruleContext != null) {
@@ -421,7 +426,7 @@ public NestedSet<String> getJvmOptions() {
     return jvmOptions;
   }
 
-  /** @return whether JavaBuilders supports running as a persistent worker or not */
+  /** Returns whether JavaBuilders supports running as a persistent worker or not. */
   public boolean getJavacSupportsWorkers() {
     return javacSupportsWorkers;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaConfigurationApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaConfigurationApi.java
index 54b7a7c13cfaad..da583f1b5819b9 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaConfigurationApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaConfigurationApi.java
@@ -79,4 +79,16 @@ public interface JavaConfigurationApi extends StarlarkValue {
       doc = "Returns true if empty java_import jars are not allowed.",
       useStarlarkThread = true)
   boolean getDisallowJavaImportEmptyJarsInStarlark(StarlarkThread thread) throws EvalException;
+
+  @StarlarkMethod(
+      name = "use_ijars",
+      doc = "Returns true iff Java compilation should use ijars.",
+      useStarlarkThread = true)
+  boolean getUseIjarsInStarlark(StarlarkThread thread) throws EvalException;
+
+  @StarlarkMethod(
+      name = "disallow_java_import_exports",
+      doc = "Returns true if java_import exports are not allowed.",
+      useStarlarkThread = true)
+  boolean getDisallowJavaImportExportsInStarlark(StarlarkThread thread) throws EvalException;
 }
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaToolchainStarlarkApiProviderApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaToolchainStarlarkApiProviderApi.java
index 032c233ba3d3fb..c7041dfdaa4c41 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaToolchainStarlarkApiProviderApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/java/JavaToolchainStarlarkApiProviderApi.java
@@ -126,4 +126,12 @@ public interface JavaToolchainStarlarkApiProviderApi extends StructApi {
   @Nullable
   ImmutableList<String> getCompatibleJavacOptionsForStarlark(String key, StarlarkThread thread)
       throws EvalException;
+
+  @Nullable
+  @StarlarkMethod(
+      name = "deps_checker",
+      documented = false,
+      useStarlarkThread = true,
+      allowReturnNones = true)
+  FileApi getDepsCheckerForStarlark(StarlarkThread thread) throws EvalException;
 }
diff --git a/src/main/starlark/builtins_bzl/bazel/exports.bzl b/src/main/starlark/builtins_bzl/bazel/exports.bzl
index ac3baeb53b9f4e..0c20d0a79d9025 100644
--- a/src/main/starlark/builtins_bzl/bazel/exports.bzl
+++ b/src/main/starlark/builtins_bzl/bazel/exports.bzl
@@ -16,6 +16,7 @@
 
 load("@_builtins//:common/java/java_library.bzl", "java_library")
 load("@_builtins//:common/java/java_plugin.bzl", "java_plugin")
+load("@_builtins//:common/java/java_import.bzl", "java_import")
 load("@_builtins//:common/java/proto/java_proto_library.bzl", "java_proto_library")
 load("@_builtins//:common/cc/cc_proto_library.bzl", "cc_proto_aspect", "cc_proto_library")
 
@@ -26,6 +27,7 @@ exported_toplevels = {
 exported_rules = {
     "java_library": java_library,
     "java_plugin": java_plugin,
+    "-java_import": java_import,
     "java_proto_library": java_proto_library,
     "+cc_proto_library": cc_proto_library,
 }
diff --git a/src/main/starlark/builtins_bzl/common/java/import_deps_check.bzl b/src/main/starlark/builtins_bzl/common/java/import_deps_check.bzl
new file mode 100644
index 00000000000000..614f1365e5a5b9
--- /dev/null
+++ b/src/main/starlark/builtins_bzl/common/java/import_deps_check.bzl
@@ -0,0 +1,80 @@
+# Copyright 2022 The Bazel Authors. All rights reserved.
+#
+# Licensed 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.
+
+"""Creates the import deps checker for java rules"""
+
+load(":common/java/java_semantics.bzl", "semantics")
+
+java_common = _builtins.toplevel.java_common
+
+def import_deps_check(
+        ctx,
+        jars_to_check,
+        declared_deps,
+        transitive_deps,
+        rule_class):
+    """
+    Creates actions that checks import deps for java rules.
+
+    Args:
+      ctx: (RuleContext) Used to register the actions.
+      jars_to_check: (list[File])  A list of jars files to check.
+      declared_deps: (list[File]) A list of direct dependencies.
+      transitive_deps: (list[File]) A list of transitive dependencies.
+      rule_class: (String) Rule class.
+
+    Returns:
+      (File) Output file of the created action.
+    """
+    java_toolchain = semantics.find_java_toolchain(ctx)
+    deps_checker = java_toolchain.deps_checker()
+    if deps_checker == None:
+        return None
+
+    jdeps_output = ctx.actions.declare_file("_%s/%s/jdeps.proto" % (rule_class, ctx.label.name))
+
+    args = ctx.actions.args()
+    args.add("-jar", deps_checker)
+    args.add_all(jars_to_check, before_each = "--input")
+    args.add_all(declared_deps, before_each = "--directdep")
+    args.add_all(
+        depset(order = "preorder", transitive = [declared_deps, transitive_deps]),
+        before_each = "--classpath_entry",
+    )
+    args.add_all(java_toolchain.bootclasspath, before_each = "--bootclasspath_entry")
+    args.add("--checking_mode=error")
+    args.add("--jdeps_output", jdeps_output)
+    args.add("--rule_label", ctx.label)
+
+    inputs = depset(
+        jars_to_check,
+        transitive = [
+            declared_deps,
+            transitive_deps,
+            java_toolchain.bootclasspath,
+        ],
+    )
+    tools = [deps_checker, java_toolchain.java_runtime.files]
+
+    ctx.actions.run(
+        mnemonic = "ImportDepsChecker",
+        progress_message = "Checking the completeness of the deps for %s" % jars_to_check,
+        executable = java_toolchain.java_runtime.java_executable_exec_path,
+        arguments = [args],
+        inputs = inputs,
+        outputs = [jdeps_output],
+        tools = tools,
+    )
+
+    return jdeps_output
diff --git a/src/main/starlark/builtins_bzl/common/java/java_import.bzl b/src/main/starlark/builtins_bzl/common/java/java_import.bzl
new file mode 100644
index 00000000000000..344fa2cabc5763
--- /dev/null
+++ b/src/main/starlark/builtins_bzl/common/java/java_import.bzl
@@ -0,0 +1,263 @@
+# Copyright 2021 The Bazel Authors. All rights reserved.
+#
+# Licensed 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.
+
+"""
+Definition of java_import rule.
+"""
+
+load(":common/java/java_common.bzl", "construct_defaultinfo")
+load(":common/java/java_semantics.bzl", "semantics")
+load(":common/java/proguard_validation.bzl", "VALIDATE_PROGUARD_SPECS_IMPLICIT_ATTRS", "validate_proguard_specs")
+load(":common/rule_util.bzl", "merge_attrs")
+load(":common/java/java_util.bzl", "create_single_jar")
+load(":common/java/import_deps_check.bzl", "import_deps_check")
+
+JavaInfo = _builtins.toplevel.JavaInfo
+CcInfo = _builtins.toplevel.CcInfo
+java_common = _builtins.toplevel.java_common
+
+def _filter_provider(provider, *attrs):
+    return [dep[provider] for attr in attrs for dep in attr if provider in dep]
+
+def _collect_jars(ctx, jars):
+    jars_dict = {}
+    for info in jars:
+        if JavaInfo in info:
+            fail("//" + ctx.label.package + ":" + ctx.attr.name + ": should not refer to Java rules")
+        for jar in info.files.to_list():
+            jar_path = jar.dirname + jar.basename
+            if jars_dict.get(jar_path) != None:
+                fail("in jars attribute of java_import rule //" + ctx.label.package + ":" + ctx.attr.name + ": " + jar.basename + " is a duplicate")
+            jars_dict[jar_path] = jar
+    return [jar_tuple[1] for jar_tuple in jars_dict.items()] if len(jars_dict.items()) > 0 else []
+
+def _process_with_ijars_if_needed(jars, ctx):
+    file_dict = {}
+    use_ijars = ctx.fragments.java.use_ijars()
+    for jar in jars:
+        interface_jar = jar
+        if use_ijars:
+            ijar_basename = jar.short_path.removesuffix("." + jar.extension) + "-ijar.jar"
+            interface_jar_directory = "_ijar/" + ctx.label.name + "/" + ijar_basename
+
+            interface_jar = ctx.actions.declare_file(interface_jar_directory)
+            create_single_jar(
+                ctx,
+                interface_jar,
+                depset([jar]),
+            )
+        file_dict[jar] = interface_jar
+
+    return file_dict
+
+def _check_export_error(ctx, exports):
+    if len(exports) != 0 and (ctx.fragments.java.disallow_java_import_exports() or
+                              (hasattr(ctx.attr, "_allowlist_java_import_exports") and not getattr(ctx.attr, "_allowlist_java_import_exports").isAvailableFor(ctx.label))):
+        fail("java_import.exports is no longer supported; use java_import.deps instead")
+
+def _check_empty_jars_error(ctx, jars):
+    # TODO(kotlaja): Remove temporary incompatible flag [disallow_java_import_empty_jars] once migration is done.
+    if len(jars) == 0 and ctx.fragments.java.disallow_java_import_empty_jars() and hasattr(ctx.attr, "_allowlist_java_import_empty_jars") and not getattr(ctx.attr, "_allowlist_java_import_empty_jars").isAvailableFor(ctx.label):
+        fail("empty java_import.jars is no longer supported " + ctx.label.package)
+
+def _create_java_info_with_dummy_output_file(ctx, srcjar, deps, exports, runtime_deps_list, neverlink):
+    dummy_jar = ctx.actions.declare_file(ctx.label.name + "_dummy.jar")
+    dummy_src_jar = srcjar
+    if dummy_src_jar == None:
+        dummy_src_jar = ctx.actions.declare_file(ctx.label.name + "_src_dummy.java")
+        ctx.actions.write(dummy_src_jar, "")
+    return java_common.compile(
+        ctx,
+        output = dummy_jar,
+        java_toolchain = semantics.find_java_toolchain(ctx),
+        source_files = [dummy_src_jar],
+        deps = [target[JavaInfo] for target in [exports + deps] if JavaInfo in target],
+        runtime_deps = runtime_deps_list,
+        neverlink = neverlink,
+        exports = [export[JavaInfo] for export in exports if JavaInfo in export],  # Watchout, maybe you need to add them there manually.
+    )
+
+def bazel_java_import_rule(
+        ctx,
+        jars = [],
+        srcjar = None,
+        deps = [],
+        runtime_deps = [],
+        exports = [],
+        neverlink = False,
+        constraints = [],
+        proguard_specs = []):
+    """Implements java_import.
+
+    This rule allows the use of precompiled .jar files as libraries in other Java rules.
+
+    Args:
+      ctx: (RuleContext) Used to register the actions.
+      jars: (list[Artifact]) List of output jars.
+      srcjar: (Artifact) The jar containing the sources.
+      deps: (list[Target]) The list of dependent libraries.
+      runtime_deps: (list[Target]) Runtime dependencies to attach to the rule.
+      exports: (list[Target])  The list of exported libraries.
+      neverlink: (bool) Whether this rule should only be used for compilation and not at runtime.
+      constraints: (list[String]) Rule constraints.
+      proguard_specs: (list[File]) Files to be used as Proguard specification.
+
+    Returns:
+      (list[provider]) A list containing DefaultInfo, JavaInfo,
+      OutputGroupsInfo, ProguardSpecProvider providers.
+    """
+
+    _check_empty_jars_error(ctx, jars)
+    _check_export_error(ctx, exports)
+
+    collected_jars = _collect_jars(ctx, jars)
+    all_deps = _filter_provider(JavaInfo, deps, exports)
+
+    jdeps_artifact = None
+    merged_java_info = java_common.merge(all_deps)
+    if len(collected_jars) > 0 and hasattr(ctx.attr, "_allowlist_java_import_deps_checking") and not ctx.attr._allowlist_java_import_deps_checking.isAvailableFor(ctx.label) and "incomplete-deps" not in ctx.attr.tags:
+        jdeps_artifact = import_deps_check(
+            ctx,
+            collected_jars,
+            merged_java_info.compile_jars,
+            merged_java_info.transitive_compile_time_jars,
+            "java_import",
+        )
+
+    compilation_to_runtime_jar_map = _process_with_ijars_if_needed(collected_jars, ctx)
+    runtime_deps_list = [runtime_dep[JavaInfo] for runtime_dep in runtime_deps if JavaInfo in runtime_dep]
+    java_info = None
+    if len(collected_jars) > 0:
+        java_infos = []
+        for jar in collected_jars:
+            java_infos.append(JavaInfo(
+                output_jar = jar,
+                compile_jar = compilation_to_runtime_jar_map[jar],
+                deps = all_deps,
+                runtime_deps = runtime_deps_list,
+                neverlink = neverlink,
+                source_jar = srcjar,
+                exports = [export[JavaInfo] for export in exports if JavaInfo in export],  # Watchout, maybe you need to add them there manually.
+            ))
+        java_info = java_common.merge(java_infos)
+    else:
+        # TODO(kotlaja): Remove next line once all java_import targets with empty jars attribute are cleaned from depot (b/246559727).
+        java_info = _create_java_info_with_dummy_output_file(ctx, srcjar, deps, exports, runtime_deps_list, neverlink)
+
+    if len(constraints):
+        java_info = semantics.add_constraints(java_info, constraints)
+
+    target = {"JavaInfo": java_info}
+
+    target["ProguardSpecProvider"] = validate_proguard_specs(
+        ctx,
+        proguard_specs,
+        [deps, runtime_deps, exports],
+    )
+
+    # TODO(kotlaja): Revise if collected_runtimes can be added into construct_defaultinfo directly.
+    collected_runtimes = []
+    for runtime_dep in ctx.attr.runtime_deps:
+        collected_runtimes.extend(runtime_dep.files.to_list())
+
+    target["DefaultInfo"] = construct_defaultinfo(
+        ctx,
+        collected_jars,
+        collected_jars + collected_runtimes,
+        neverlink,
+        exports,
+    )
+
+    output_group_src_jars = depset() if srcjar == None else depset([srcjar])
+    target["OutputGroupInfo"] = OutputGroupInfo(
+        **{
+            "_source_jars": output_group_src_jars,
+            "_direct_source_jars": output_group_src_jars,
+            "_validation": depset() if jdeps_artifact == None else depset([jdeps_artifact]),
+            "_hidden_top_level_INTERNAL_": target["ProguardSpecProvider"].specs,
+        }
+    )
+    return target
+
+def _proxy(ctx):
+    return bazel_java_import_rule(
+        ctx,
+        ctx.attr.jars,
+        ctx.file.srcjar,
+        ctx.attr.deps,
+        ctx.attr.runtime_deps,
+        ctx.attr.exports,
+        ctx.attr.neverlink,
+        ctx.attr.constraints,
+        ctx.files.proguard_specs,
+    ).values()
+
+_ALLOWED_RULES_IN_DEPS_FOR_JAVA_IMPORT = [
+    "java_library",
+    "java_import",
+    "cc_library",
+    "cc_binary",
+]
+
+JAVA_IMPORT_ATTRS = merge_attrs(
+    VALIDATE_PROGUARD_SPECS_IMPLICIT_ATTRS,
+    {
+        "data": attr.label_list(
+            allow_files = True,
+            flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
+        ),
+        "deps": attr.label_list(
+            providers = [JavaInfo],
+            allow_rules = _ALLOWED_RULES_IN_DEPS_FOR_JAVA_IMPORT,
+        ),
+        "exports": attr.label_list(
+            providers = [JavaInfo],
+            allow_rules = _ALLOWED_RULES_IN_DEPS_FOR_JAVA_IMPORT,
+        ),
+        "runtime_deps": attr.label_list(
+            allow_files = [".jar"],
+            allow_rules = _ALLOWED_RULES_IN_DEPS_FOR_JAVA_IMPORT,
+            providers = [[CcInfo], [JavaInfo]],
+            flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"],
+        ),
+        # JavaImportBazeRule attr
+        "jars": attr.label_list(
+            allow_files = [".jar"],
+            mandatory = True,
+        ),
+        "srcjar": attr.label(
+            allow_single_file = [".srcjar", ".jar"],
+            flags = ["DIRECT_COMPILE_TIME_INPUT"],
+        ),
+        "neverlink": attr.bool(
+            default = False,
+        ),
+        "constraints": attr.string_list(),
+        # ProguardLibraryRule attr
+        "proguard_specs": attr.label_list(
+            allow_files = True,
+        ),
+        # Additional attrs
+        "licenses": attr.string_list(),
+        "_java_toolchain_type": attr.label(default = semantics.JAVA_TOOLCHAIN_TYPE),
+    },
+)
+
+java_import = rule(
+    _proxy,
+    attrs = JAVA_IMPORT_ATTRS,
+    provides = [JavaInfo],
+    fragments = ["java", "cpp"],
+    toolchains = [semantics.JAVA_TOOLCHAIN],
+)
diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java
index bb270a2aa0b196..9c3b76d22c8848 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaStarlarkApiTest.java
@@ -2563,6 +2563,48 @@ public void strictJavaDepsFlagExposed_error() throws Exception {
     assertThat(((String) info.getValue("strict_java_deps"))).isEqualTo("error");
   }
 
+  @Test
+  public void useIjars_fails() throws Exception {
+    setBuildLanguageOptions("--experimental_builtins_injection_override=+java_import");
+    scratch.file(
+        "foo/rule.bzl",
+        "result = provider()",
+        "def _impl(ctx):",
+        "  ctx.fragments.java.use_ijars()",
+        "  return []",
+        "myrule = rule(",
+        "  implementation=_impl,",
+        "  fragments = ['java']",
+        ")");
+    scratch.file("foo/BUILD", "load(':rule.bzl', 'myrule')", "myrule(name='myrule')");
+    reporter.removeHandler(failFastHandler);
+
+    getConfiguredTarget("//foo:myrule");
+
+    assertContainsEvent("Rule in 'foo' cannot use private API");
+  }
+
+  @Test
+  public void disallowJavaImportExports_fails() throws Exception {
+    setBuildLanguageOptions("--experimental_builtins_injection_override=+java_import");
+    scratch.file(
+        "foo/rule.bzl",
+        "result = provider()",
+        "def _impl(ctx):",
+        "  ctx.fragments.java.disallow_java_import_exports()",
+        "  return []",
+        "myrule = rule(",
+        "  implementation=_impl,",
+        "  fragments = ['java']",
+        ")");
+    scratch.file("foo/BUILD", "load(':rule.bzl', 'myrule')", "myrule(name='myrule')");
+    reporter.removeHandler(failFastHandler);
+
+    getConfiguredTarget("//foo:myrule");
+
+    assertContainsEvent("Rule in 'foo' cannot use private API");
+  }
+
   @Test
   public void mergeRuntimeOutputJarsTest() throws Exception {
     scratch.file(
diff --git a/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java b/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java
index 5d38681f4d64d9..63415d3d3800da 100644
--- a/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java
+++ b/src/test/java/com/google/devtools/build/lib/view/java/JavaImportConfiguredTargetTest.java
@@ -50,6 +50,11 @@
 @RunWith(JUnit4.class)
 public class JavaImportConfiguredTargetTest extends BuildViewTestCase {
 
+  @Before
+  public void setCommandLineFlags() throws Exception {
+    setBuildLanguageOptions("--experimental_google_legacy_api");
+  }
+
   @Before
   public final void writeBuildFile() throws Exception {
     scratch.file(
@@ -66,6 +71,12 @@ public final void writeBuildFile() throws Exception {
         "    name = 'java_import_exports',",
         "    packages = ['//...'],",
         ")");
+    scratch.overwriteFile(
+        "tools/allowlists/java_import_empty_jars/BUILD",
+        "package_group(",
+        "    name = 'java_import_empty_jars',",
+        "    packages = [],",
+        ")");
   }
 
   @Test
@@ -259,7 +270,9 @@ public void testRequiresJars() throws Exception {
 
   @Test
   public void testPermitsEmptyJars() throws Exception {
+    useConfiguration("--incompatible_disallow_java_import_empty_jars=0");
     scratchConfiguredTarget("pkg", "rule", "java_import(name = 'rule', jars = [])");
+    assertNoEvents();
   }
 
   @Test
diff --git a/src/test/shell/integration/java_integration_test.sh b/src/test/shell/integration/java_integration_test.sh
index 64c79668216a02..6bf01aa113a83d 100755
--- a/src/test/shell/integration/java_integration_test.sh
+++ b/src/test/shell/integration/java_integration_test.sh
@@ -818,6 +818,35 @@ EOF
   expect_log "symbol not found missing.NoSuch"
 }
 
+function test_java_import_with_empty_jars_attribute() {
+  local -r pkg="${FUNCNAME[0]}"
+  mkdir -p $pkg/java/hello/ || fail "Expected success"
+  cat > $pkg/java/hello/Hello.java <<EOF
+package hello;
+public class Hello {
+  public static void main(String[] args) {
+    System.out.println("Hello World!");
+  }
+}
+EOF
+  cat > $pkg/java/hello/BUILD <<EOF
+java_import(
+    name='empty_java_import',
+    jars=[]
+)
+java_binary(
+    name='hello',
+    srcs=['Hello.java'],
+    deps=[':empty_java_import'],
+    main_class = 'hello.Hello'
+)
+EOF
+  bazel build --incompatible_disallow_java_import_empty_jars=0 //$pkg/java/hello:hello //$pkg/java/hello:hello_deploy.jar >& "$TEST_log" \
+      || fail "Expected success"
+  bazel run //$pkg/java/hello:hello -- --singlejar >& "$TEST_log"
+  expect_log "Hello World!"
+}
+
 function test_arg_compile_action() {
   local package="${FUNCNAME[0]}"
   mkdir -p "${package}"